前端面试总结

一:浏览器事件循环机制个人理解(EventLoop)

1:浏览器进程模型
    要理解浏览器事件循环机制首先要明白浏览器的进程模型,进程就是一个
程序运行需要给其分配一块专属的内存空间,可以把这块内存空间简单理解为
进程。进程之间是相互独立的,如果进程之间需要通信则需要对方同意。
2:线程模型
    既然分配内存空间有了进程之后就可以运行程序了,程序运行之后总需要
有人干活,这是就需要引入线程的概念,程序运行之后会默认开启一个线程,
称之为主线程。一个进程至少包含一个线程。当程序需要执行多份代码段,主线
程就会启动更多的线程来一块运行。所以一个一个进程可以包含多个线程。可以
拿游戏里的主任务和副本任务进行理解。
3:浏览器进程和线程(Goole为例)
    既然知道了进程和线程。那么就要知道浏览器有哪些进程和线程。首先浏
览器是一个多进程、多线程的应用程序。这是为了避免引发浏览器一连串的崩
溃。所以浏览器会在运行之后启动多个进程。浏览器很有很多进程,其中主要
的有三个进程,分别是:
浏览器进程:负责浏览器工程区展示、用户交互、子进程管理等。
网络进程:负责加载网络资源,网络进程内部会启用很多个线程来处理不同的
         网络请求。
渲染进程(重点):**渲染进程启动后,会启动一个主线程进行解析执行HTML、
CSS、JS代码。默认情况下每一个新标签页就是一个渲染进程**
4:渲染主线程工作原理(事件循环机制原理)
    知道了渲染主线程,就要知道它的工作原理,我们知道他需要处理很多
任务,包括解析HTML、解析CSS、计算样式、处理布局、执行js代码、处理
计时器、回调函数等等。那么这么多任务,渲染主线程是怎么调度任务的呢,
这就需要引入一个消息队列的概念。渲染主线程在最开始启动的时候是默认
进入无限循环的的状态,他会将所需要处理的任务放到一个消息队列里进行
排队,同时在多线程处理的任务如果需要主线程处理也会将任务放到消息队
列里,然后由主线程从消息队列里取任务进行执行,直到消息队列里没有任务
之后,渲染主线程则会进行休眠状态,如果有新任务进入消息队列,则会唤醒
主线程进入下一次循环,进行任务执行。这样一来,任务就可以有条不紊的
执行下去,这一过程,称之为消息循环(Goole浏览器标准),
也称事件循环(W3C标准)。
4:消息队列(任务队列)类型优先级
    根据W3C最新解释:消息队列里的任务都会有一个任务类型,任务是没有
优先级的,但是消息队列是有优先级的,在一次事件循环中,浏览器会根据
实际情况从消息队列中取任务进行执行。同时浏览器必须准备一个微队列
(microtask que)微队列里的任务优先级高于其他队列里的任务,在主线程
里的同步任务执行完毕后,会优先从微队列里取任务进行执行。
在当前Chrome的实现中,至少包含下面三种消息队列:
*(w3c最新解释已经取消宏队列的说法)*[w3c任务队列解释](https://html.spec.whatwg.org/multipage/webappapis.html#queuing-tasks)
1:微队列:优先级最高 用于存放最快执行的任务,
          比方说Promies、MutationObserver
2:交互队列:优先级高 用户存放用户交互后需要
            执行的任务 addEventListening
3:延时队:优先级中 用于存放需要延迟操作的一
          些任务 setTimeout    
5:消息队列(任务队列)类型优先级例题
        window.requestIdleCallback(() => {
          console.log("3");
        });
        
        setTimeout(() => {
          console.log("1");
        }, 0);
        
        async function a1() {
          console.log("4");
          await a2();
          console.log("5");
        }
        
        async function a2() {
          console.log("6");
        }
        
        a1();
        
        new Promise((resolve) => {
          console.log("7");
          resolve();
          console.log("8");
        }).then(() => {
          console.log("9");
        });
        
        console.log("10");

二:垃圾回收机制

1:概念
   浏览器的 Javascript 具有自动垃圾回收机制,垃圾收集器会定期
(周期性)找出那些不在继续使用的变量,然后释放其内存。
2:垃圾回收的方式
   1)标记清除
      js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,
例如,在一个函数中声明一个变量,就将这个变量标记为"进入环境"  
      从逻辑上讲,从逻辑上讲,永远不能释放进入环境变量所占用
的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量
离开环境时,则将其标记为"离开环境"。
      2)引用计数
      引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个
变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是 1。
      相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值
的引用次数就减 1。当这个引用次数变成 0 时,则说明没有办法再访问这个
值了,因而就可以将其所占的内存空间给收回来。

三:JS异步理解

    JS是单线程语言,它是运行在浏览器的渲染主线程中的,
渲染主线程只有一个,而渲染主线程需要执行很多任务,比如
HTML解析,CSS解析,样式计算,层级调整,JS代码执行等等,
如果采用同步的方式,极容易造成线程阻塞,影响后续任务的
执行及页面渲染。导致页面无法及时更新,给用户造成页面卡顿
现象。
    所以浏览器采用异步的方式来避免,具体的做法就是比方
在线程任务队列里的某一个任务是延迟任务,或是回调函数等,
主线程会让其他线程去处理,主线程立即结束当前任务,转而
去执行下一个任务,当其他线程的任务执行完成时,再将需要
继续执行的函数作为任务放到主线程的消息队列里等待主线程
继续执行。这样就不会影响主线程的操作流程,进而造成主线
程阻塞。

四:原形链的理解

    在js里,继承机制是原型继承。继承的起点是 对象的原型(Object prototype)。
    一切皆为对象,只要是对象,就会有 proto 属性,该属性存储了指向其构造的指针。
    Object prototype也是对象,其 proto 指向null。
    对象分为两种:函数对象和普通对象,只有函数对象拥有『原型』对象(prototype)。
    prototype的本质是普通对象。
    Function prototype比较特殊,是没有prototype的函数对象。
    new操作得到的对象是普通对象。
    当调取一个对象的属性时,会先在本身查找,若无,就根据 proto 找到构造原型,
若无,继续往上找。最后会到达顶层Object prototype,它的 proto 指向null,均无结果
则返回undefined,结束。
    由 proto 串起的路径就是『原型链』。
    通过prototype可以给所有子类共享属性

你可能感兴趣的:(前端面试)