「复习大纲02」-菜鸡前端知识体系整理

139 阅读8分钟

四、JavaScript(ES6)

1、模块化

2、变量声明

  • let const、var 使用场景对比
场景letconstvar
定义层面定义变量,只能在块作用域访问
不能跨函数
定义的是常量,使用的时候必须初始化
只能在块作用域访问
不能修改
定义的是变量,是全局的
没有块的概念,可以跨块访问
但是不能跨函数

3、数组扩展

1、扩展运算符...

  • 扩展运算符是三个点(...)
  • 就好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列

什么是rest参数(...rest)

rest参数(形式为"...变量名"),其中rest参数搭配的变量是一个数组,可以使用数组的一切操作。

console.log(...[1, 2, 3]);
// 1 2 3
console.log(1,...[2, 3, 4],5);
// 1 2 3 4 5
  • 适用的一些场景

  • 场景一、将一个数组添加到另一个数组尾部

// ES5
var arr1 =[1,2,3];
var arr2 =[4,5,6];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); 
// [1,2,3,4,5,6]

// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

arr1.push(...arr2);

console.log(arr1, "合并数组"); 

// [1, 2, 3, 4, 5, 6]

  • 场景二、用于合并数组
[1,2].concat(more) // ES5
[1,2,...more] //ES6
  • 场景三、可以将字符串转成数组
// ES5
const str="hello";
const a=str.split('');
console.log(b);
// ["h", "e", "l", "l", "o"]

// ES6
const str = "hello";
const b = [...str];
console.log(b);
// ["h", "e", "l", "l", "o"]
  • 场景四、与解构赋值结合
// ES5
a = list[0],rest = list.slice(1)
// ES6
[a,...rest]=list

// 一些常见的例子
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest);// [2,3,4,5]

const [first,...rest]=[];
console.log(first); // undefined
console.log(rest);// []

const[first,...rest]=["foo"];
console.log(first); // "foo"
console.log(rest); // []

// !!!如果将扩展运算符用于数组赋值,只能放在参数的最后一位,不然回报错
// 例如

const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错
const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 报错
  • 场景五、复制数组
//ES5
const a1=[1,2];
const a2=a1.concat();
a2[0]=2

[1,2]

//ES6
const a1=[1,2];
// 写法一
const a2=[...a1];
// 写法二
const[...a2]=a1;

4、函数扩展

4.1、箭头函数和不同函数的区别

4.2、解构函数

5、Promise

6、Class

五、浏览器基础

1、浏览器渲染原理

渲染一个html页面都做了哪些步骤

  • 生成DOM树
  • 生成CSS树 具体渲染过程
  • 页面加载时,浏览器把获取到的HTML代码会解析成1个DOM树;
  • DOM树里面会包含所有HTML标签、JS动态添加的元素等;
  • 那么接着就是CSSOM树的构建,也就是CSS下载完后,对CSS进行解析成对象,组成CSSOM树;
  • DOM树与CSSOM树结合,生成渲染树Render Tree;

回流和重绘

请描述下叫做回流?

回流是整个页面进行重排,也就是页面所有dom元素渲染。影响了这个页面的尺寸、布局、隐藏等。

请描述下是重绘?

当Render Tree树中某个DOM元素的属性需要更新,是影响外观且不影响布局的,则称之为重绘。

实际开发中如何避免回流的发生

  • 尽可能在DOM末梢通过改变class来修改元素的style属性,尽可能减少受影响的dom元素;
  • 避免内联样式,使用class的样式进行设置样式;
  • 减少元素批量修改的次数
  • 设置动画元素position属性为fixed或者absolute。由于当前元素从DOM流中独立出来,因此受影响的只有当前元素,元素repaint;
  • CSS硬件加速 transform/opacity/filters...... 但如果用得不好就会引起内存过大,消耗性能等麻烦;
  • 动画精度太强,会造成更多次的重绘/回流,必要的时候牺牲精度,满足性能损耗,获取性能和平滑度平衡;
  • 避免使用tale进行布局,改用div;

2、浏览器缓的存储

说一下Cookie、sessionStorage、localstorage、indexDB区别

场景sessionStoragelocalstorageCookieindexDB
数据生命周期页面关闭就清理除非人为清理,
否则都会一直存在
服务器生成,可以设置过期时间
在所有同源窗口
中都是共存的
除非人为清理,
否则都会一直存在
数据存储大小<=5M<=5M<4k无限
与服务端通信不参与不参与会携带在header中,对于请求性能影响不参与
使用场景拥有独立特性的数据持久保存的数据保存回话信息-

说说Cookie是一个什么东西?

是网站为了标识用户身份而储存在用户本地终端的数据,通过同源的http携带传递。记录浏览器和服务端间来回的传递。

Cookie也是会存在安全性的问题,说说怎么解决?

  • 设置httpOnly,减少XSS攻击。
  • 设置SameSite,可以让cookie不随跨站请求发出。

3、事件机制

3.1、事件触发三个阶段
3.2、注册事件
3.3、事件委托/事件代理

4、Event Loop

进程和线程

  • 进程(资源分配的最小单位)
    • 1、 应用程序的执行实例。
    • 2、每一个进程都是由私有的虚拟地址空间、代码、数据、和和其他系统资源组成。
  • 线程(程序分配的最小单位)
    • 1、线程是进程内的一个独立执行单元,在不同的线程之间是可以共享进程资源的。
场景进程线程
拥有独立的堆栈空间和数据段拥有独立的堆栈空间,但是共享数据段
启动新的进程必须分配独立的空间
还要建立众多的数据表维护代码段、堆栈段、数据段
彼此之前使用相同的地址空间,
共享大部分数据,

浏览器中的Event Loop

执行栈与事件队列

  • 当js代码执行的时候会将不同的变量存于内存中的不同位置,堆(heap)/栈(stack)中加以区分,

  • 堆存放一些对象,栈里存在一些基础的类变量、对象指针,

  • 当所有的同步任务都在主线程上执行时,这些任务被排列在一个单独的地方,形成一个执行栈

  • js引擎在解析代码段时,会将同步任务顺序加入执行栈依次执行,

  • 当遇到异步并行的时候,并不会一直等待,而是将异步任务挂起,--->先执行同步任务--->

宏任务(marco task)、微任务(micro task)

  • 异步任务又分为宏任务和微任务,执行方式,microtask->marotask

  • 宏任务、微任务分类

    • microtask-> process.nextTick(node独有), Promises, Object.observe(废弃), MutationObserver
    • marotask-> script(整体代码), setTimeout, setInterval, setImmediate(node独有), I/O, UI rendering

Node中的Event Loop

  • timers,执行定时器队列中的回调,setTimeout()....
  • i/o callbacks,这个阶段执行几乎所有的回调,但是不包括close事件,定时器和setImmediate()的回调
  • idle,prepare,这个阶段仅在内部使用,
  • poll,等待i/o事件,node在一些特殊情况下阻塞在这里
  • cheack,setImmediate()的回调在这阶段执行
  • close callbacks,
举个例子(2MicroTask队列与MacroTask队列
setTimeout(function () {
   console.log(1);
});
console.log(2);
process.nextTick(() => {
   console.log(3);
});
new Promise(function (resolve, rejected) {
   console.log(4);
   resolve()
}).then(res=>{
   console.log(5);
})
setImmediate(function () {
   console.log(6)
})
console.log('end');

2,4,end,3,5,1,6

参考文献

如何解释Event Loop面试官才满意?

浏览器的event loop和node的event loop

5、浏览器跨域

同源策略

不同域的客户端脚本在无明确授权的情况下,不能读取对方资源。

产生跨域情况

同一协议、同一域名、同一端口,如果当其中一个不满足的时候,就会产生跨域问题。

解决跨域的方案

方案一、jsonp

  • 实现原理

    • 利用js标签(script,img, iframe)里面的跨域特性进行跨域数据访问。
    • js标签里面存在的是一个跨域的url,实际执行的时候通过这个url获得一段字符串。
    • 返回的字符串必须是一个合法的js调用,通过eval这个字符串来完成对获得数据的处理。
  • 实现方式

//js原生实现jsonp

// A部分中的html代码
<script type="text/javascript">
   function callback(data) {
       alert(data.message);
   }
   //添加<script>标签的方法
   function addScriptTag(src){
   var script = document.createElement('script');
       script.setAttribute("type","text/javascript");
       script.src = src;
       document.body.appendChild(script);
   }
   
   window.onload = function(){
       addScriptTag("http://localhost:20002/test.js");
   }
</script>
// B部分中获取数据部分js
//调用callback函数,并以json数据形式作为阐述传递,完成回调

callback({message:"success"});
  • jq封装实现jsonp
$.ajax({  
  url: "http://localhost:9090/student",  
  type: "GET",  
  dataType: "jsonp", //指定服务器返回的数据类型  
  jsonp:"thefun" ,// 指定参数名称
  jsonpCallback:"showData", // 指定回调函数名称  
  success: function (data) {      
  var result = JSON.stringify(data); //json对象转成字符串      
  	$("#text").val(result); 
  }
});
  • jsonp,只能使用get方式发起跨域请求,跨域请求需要服务端配合,要设置callback,才能完成跨域请求。

方案二、cors

  • 分类
  • 1.1、简单请求
    • 请求方法,主要是head,get,post,三种之一的。
    • HTTP的头信息不超出这几种字段
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
  • 1.2、非简单请求
    • 预检请求,是对服务器有特殊要求的请求,比如put\delete,或者就是Content-Type:application/json;
    • 浏览器先询问服务器,当网页所在的域名是否在服务器的许可名单,以及可以使用那些HTTP动词和信息字段,得到肯定答复,浏览器才会发出正式XMLHttpRequest请求。
    • 预请求基础设置,一般使用方法,options。主要是在origin\access-Control-Request-Method\access-Control-Request-Headers
  • 前端配置

    • 为了要携带cookie, withCredentials 为true
  • 后端配置

    • origin // 跨域请求来自哪里

    • access-control-allow-methods // 请求可能用到的什么方法 get put post

    • access-Control-Request-Headers // 请求时可能用到的头部

    • access-Control-Allow-Origin // * 表示任何请求都可访问

    • access-Control-Allow-Credentials // 是否允许发送cookie、 true

    • access-control-allow-headers // 表示跨域支持的请求头有哪些

方案三、nginx

通过反向代理,使得请求地址和服务器同域

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
location /api {
   proxy_pass https://b.test.com; # 设置代理服务器的协议和地址
   proxy_cookie_domain b.test.com  a.test.com; # 修改cookie,针对request和response互相写入cookie
}       

跨域方案对比

cors、nginx做对比

场景corsnginx
前端withCredentials 为true
后端setHeader:ACA-Origin、ACA-Method、
ACA-Credentials等
服务器Nginx配置
移值性高、无需额外配置低,每套环境可能均不相同
安全性来源可控,直接追溯通过X-Forward-For追溯多级来源
( X-Forwarded-For:client, proxy1, proxy2)
扩展性黑白名单控制更新配置,跨域模型会产生变化

参考文献

简单对比一下CORS跨域与Nginx反向代理跨域优劣

6、浏览器内存

7、浏览器的垃圾回收

8、浏览器的执行机制

9、浏览器的安全