前端硬核知识点(三)

简述浏览器的渲染过程,回流(重排)和重绘(reflow和repaint)在渲染过程中的哪一部分?

html文档解析成dom树,css解析成css对象模型(CSS Object Model),两者合并生成渲染树(rendering tree),渲染树进行布局(layer)即根据渲染树带有的位置信息计算位置,最后绘制(painting)屏幕就显示了页面。

image.png

回流:布局(layer)发生变化需要倒回去重新渲染,这个回退就是回流(reflow)。因为绘制发生在布局的下一步,所以回流必定触发重绘

重绘:绘制时背景色,文字颜色等变动,不影响位置,即重绘(repaint)

补充:渲染引擎为两种,firefox的geoko和chrome和safari的webkit

文档参考:https://www.jianshu.com/p/e6252dc9be32

简述什么是 XSS 攻击以及 CSRF 攻击?

CSRF(Cross-site request forgery):跨站请求伪造。

image.png

cookie在同一个浏览器是共享的,网站a的登录凭证放在cookie内,同时在恶意网站b点操作,触发事件,网站b拿着网站a的cooike凭证鉴权,成功后访问网站a的后台进行作恶
措施:使用token的方式,比如JWT

XSS(Cross Site Scripting):跨域脚本攻击。

核心原理是:不需要你做任何的登录认证,通过合法的操作(比如在url中输入、在评论框中输入),向你的页面注入脚本(可能是js、hmtl代码块等),造成D-doss攻击(比如弹窗广告,频繁请求后台)
措施:参考:https://www.freebuf.com/articles/web/185654.html

简述 CSS 有哪些上下文类型?
  1. BFC(Block Formatting Context),块级格式上下文
  2. IFC(Inline formatting context),内联格式上下文
  3. FFC,弹性盒格式上下文(CSS3新布局属性
  4. GFC,网格格式上下文(CSS3新布局属性

参考:https://blog.youkuaiyun.com/web_only_/article/details/100709188

简述 ES6 的新特性

常用的有:
1、变量声明:const和let
2、模板字符串:${param}拼接
3、箭头函数(Arrow Functions):()=>{}
4、对象和数组解构:let {a,b}=object1
参考:https://www.jianshu.com/p/ac1787f6c50f

了解过 Gulp Grunt 吗?简述他们的优势以及劣势

参考:https://www.jianshu.com/p/1a255e740710

Javascript 可以保存的最大数值是多少?

2的53次方,Math.pow(2,53) 9007199254740992

优化首屏渲染的方式有哪几种?
  • Vue-Router路由懒加载(利用Webpack的代码切割)
  • 使用CDN加速,将通用的库从vendor进行抽离
  • Nginx的gzip压缩
  • Vue异步组件
  • 服务端渲染SSR
  • 如果使用了一些UI库,采用按需加载
  • Webpack开启gzip压缩
  • 如果首屏为登录页,可以做成多入口
  • Service Worker缓存文件处理
  • 使用link标签的rel属性设置 prefetch(这段资源将会在未来某个导航或者功能要用到,但是本资源的下载顺序权重比较低,prefetch通常用于加速下一次导航)、preload(preload将会把资源得下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度)
JavaScript 中的严格模式是什么,有什么作用?

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode

简述输入 URL 到浏览器显示的流程

以下是有数据请求情况下,若是单页面无数据,只是路由跳转则直接最后一步渲染,即只是回流和重绘即可

客户端:

浏览器输入url,一般就是域名,部分直接是IP,如果是域名则需要解析成IP

判断本地是否存有对应域名解析成IP的关系设置,比如host文件内的配置,没有则请求DNS服务器,DNS怎么路由域名得到IP可简单理解为请求-匹配-无则向上级DNS-请求-匹配……向根DNS服务器请求,最后拿到对应IP

IP独一无二,通过IP就明确了需要请求的服务器,得到请求目标IP后,发起HTTP请求

请求传输,就是传输层的约定,使用TCP协议,使用字节流服务,并且将大块的数据分割成以报文段为单位的数据包进行管理,并为它们编号。客户端和管理端通过三次确实是否发送完成,若三次握手失败,则再次发送请求。

网络传输,网络层的约定,通过IP约定将上面分割的数据包传输给目标服务器,为了保证目标真实准确,传输前会再确定目标服务器的MAC地址。ip可更换,mac地址一般固定,且可通过ARP协议得到mac地址

有MAC地址,则到了数据链路层,向目标服务器进行数据传输,客户端流程结束

服务端:

在数据链路层接到数据包,向上层转发,经过传输层时,反向将数据包组装成原来的http请求内容

服务器收到请求,ip决定了是哪个服务器,端口则决定了向服务器上哪个应用作请求。数据请求类接口在对应应用内,请求数据,正常则响应状态码200,异常则响应异常码

服务器返回数据,客户端拿到数据,页面渲染

渲染:

html文档解析成dom树,css解析成css对象模型(CSS Object Model),两者合并生成渲染树(rendering tree),渲染树进行布局(layer)即根据渲染树带有的位置信息计算位置,最后绘制(painting)屏幕就显示了页面。

简述 Javascript 中 this 的指向有哪些

1、普通函数调用

没特殊意外,就是指向全局对象-window

其中,let允许把变量的作用域限制在块级域中;var申明变量要么是全局的,要么是函数级的,而无法是块级的。

// 以下都在浏览器输出
// let
let username = "老大";
!function fn(){
    console.log(this.username);   // undefined,let 申明在块内,this调用是全局的
}() // 立即执行函数

// var
var name = "老大";
!function fn(){
    console.log(this.name); // 老大,var 申明在全局,this调用是全局,可以拿到
}()

// window
// 所有浏览器都支持 window 对象。它代表浏览器的窗口。
// 所有全局 JavaScript 对象,函数和变量自动成为 window 对象的成员。
// 全局变量是 window 对象的属性。
// 全局函数是 window 对象的方法。
window.name = "老大";
!function fn(){
    console.log(this.name); // 老大,name申明在全局,this调用全局,可以拿到
}()

2、对象函数调用

指向对象

/*对象函数调用*/
//window.name='老大';
//var name='老大';
let name='老大';
let obj={
    id:01,
    fn:function(){
        console.log(this.name);  // undefined this代表这个obj对象,对象外怎么设值,内部都是undefined
        console.log(this.id);   //01
    }
}
obj.fn();
// 例如:
let obj1={
    a:111
}
let obj2={
    a:222,
    fn:function(){
        console.log(this.a);
    }
}
obj1.fn=obj2.fn;
obj1.fn();  //111 obj得到fn属性,然后this是代表obj1对象,所以this.a是obj对象的a属性值,打印就是111

3、构造函数调用

let structureClass=function(){
    this.name='大哥';
}
let subClass1=new structureClass();
console.log(subClass1.name); // 大哥

let subClass=new structureClass();
subClass.name='大姐头';
console.log(subClass.name); // 大姐头

4、apply和call调用

let obj1={
    name:'老大'
};
let obj2={
    name:'saucxs',
    fn:function(){
        console.log(this.name);
    }
}
obj2.fn.call(obj1); // 老大
// 虽然是 obj2 调用方法,但是使用了 call ,动态的把 this 指向到 obj1 。
// 相当于这个 obj2.fn 这个执行环境是 obj1

// call 和 apply 两个主要用途:
// 1.改变 this 的指向(把 this 从 obj2 指向到 obj1 )
// 2.方法借用( obj1 没有 fn ,只是借用 obj2 方法)

// call与apply区别
// call 和 apply 的作用,完全一样,唯一的区别就是在参数上面。
// call 接收的参数不固定,第一个参数是函数体内 this 的指向,第二个参数以下是依次传入的参数。
// apply 接收两个参数,第一个参数也是函数体内 this 的指向。第二个参数是一个集合对象(数组或者类数组)

5、箭头函数调用

箭头函数里面,没有 this,箭头函数里面的 this 是继承外面的环境。

// 普通函数
let obj={
    name:'老大',
    fn:function(){
        setTimeout(function(){console.log(this.name)})
    }
}
obj.fn(); // undefined this在普通函数setTimeout里,普通函数this代表全局的,全局没有name,所以undefined
// 箭头函数
let obj={
    name:"老大",
    fn:function(){
        setTimeout(()=>{console.log(this.name)});
    }
}
obj.fn(); // 老大 this在箭头函数里,箭头函数本身没有this,向上级取,即取到对象的this,有name属性,输出`老大`

简述 jsonp 的工作原理

解决跨域调用问题

// 代码A
<script type="text/javascript">
//回调函数
function callback(data) {
    alert(data.message);
}
</script>
<script type="text/javascript" src="http://localhost:20002/test.js"></script>

// 代码B
//调用callback函数,并以json数据形式作为阐述传递,完成回调
callback({message:"success"});

// 上面就是JSONP的简单实现模式,创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调
简述 Javascript 事件冒泡和事件捕获原理
image.png

body元素是整个网页的容器,它的内部包含了一个div元素,而div的内部又包含了两个元素:h1和p。假如现在在p的内部点击了一下,外部容器div,以及最外部的body也都会触发各自的click事件。

触发顺序分两类,从外层body到内层p,称为事件捕获,例如Netscape实现的浏览器(Netscape浏览器已消失)。从内层到外层,称为事件冒泡,由微软实现,例如IE。

实际使用,由用户控制哪个方式,如标准的事件绑定使用addEventListener函数,它接收两个必传参数和一个可选参数:必传的为event(事件名,如"cick")和function(回调函数),可选的为useCapture(是否使用捕获模型,默认为false,即默认是冒泡模式)

如何解决 CSS 类名重名?

1、常用的是约定命名规范
2、使用CSS Modules

// vue中使用
<template>
  <p :class="$style.gray">
    Im gray
  </p>
</template>

<style module>
.gray {
  color: gray;
}
</style>
// 会编译为
<p class="gray_3FI3s6uz">Im gray</p>

.gray_3FI3s6uz {
    color: gray;
}
// $style.red就可以当做一个变量,并且可以在js中使用
<script>
export default {
  created () {
    console.log(this.$style.gray)
    // -> "gray_3FI3s6uz"
    // 一个基于文件名和类名生成的标识符
  }
}
</script>

简述发布订阅模式的实现方式以及原理

发布订阅模式(观察者模式),定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己的状态。

① 发布者需要一个数组类型的属性subscribers,以存储所有的订阅者;
② 订阅subscribe():将新的订阅者加入到这个数组中去;
③ 退订unsubscribe():从订阅者数组中删除某个订阅者;
④ 发布publish():循环遍历subscribers数组中的每一个元素,并通知他们,即发送消息,意味着调用订阅者的某个方法。因此,当用户订阅信息时,该订阅者需要向subscribe()提供它的其中一个方法。

subscribe()unsubscribe()publish()三种方法都需要一个type参数,因为发布者可能触发多个事件,而用户可能仅选择订阅其中一种,而不是另外一种。

  • ▲ 7 简述常见异步编程方案 (promise, generator, async) 的原理
简述 Javascript 的柯里化与逆柯里化
// 柯里化
// 普通的add函数
function add(x, y) {
    return x + y
}

// Currying(柯里化)后
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3

就是把add函数的x,y两个参数变成了先用一个函数接收x然后返回一个函数去处理y参数。柯里化就是只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

使用场景:

/ 正常正则验证字符串 reg.test(txt)
// 函数封装后
function check(reg, txt) {
    return reg.test(txt)
}
check(/\d+/g, 'test')       //false
check(/[a-z]+/g, 'test')    //true

// Currying后
function curryingCheck(reg) {
    return function(txt) {
        return reg.test(txt)
    }
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1')      // true
hasNumber('testtest')   // false
hasLetter('21212')      // false
// 这是一个正则的校验,正常来说直接调用check函数就可以了,但是如果我有很多地方都要校验是否有数字,其实就是需要将第一个参数reg进行复用,这样别的地方就能够直接调用hasNumber,hasLetter等函数,让参数能够复用,调用起来也更方便

拓展:

// 实现一个add方法,使计算结果能够满足如下预期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;

function add() {
    // 第一次执行时,定义一个数组专门用来存储所有的参数
    var _args = Array.prototype.slice.call(arguments);

    // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
    var _adder = function() {
        _args.push(...arguments);
        return _adder;
    };

    // 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
    _adder.toString = function () {
        return _args.reduce(function (a, b) {
            return a + b;
        });
    }
    return _adder;
}
add(1)(2)(3)                // 6
add(1, 2, 3)(4)             // 10
add(1)(2)(3)(4)(5)          // 15
add(2, 6)(1)                // 9

注1、Array.prototype.slice.call(arguments)意思是把调用方法的参数截取出来。

js里Array是一个类 slice是此类里的一个方法 ,那么应该Array.prototype.slice这么去用,arrayObj.slice(start, [end]) 是截取数组的一部分。call([thisObj[,arg1[arg2[[argN]]]]]) ,thisObj是一个对象的方法,arrg1~argN是参数。

所以这行意思就是说把调用方法的参数截取出来。

	function test(a,b,c,d) 
   { 
      var arg = Array.prototype.slice.call(arguments,1); 
      alert(arg); 
   } 
   test("a","b","c","d"); //b,c,d
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值