2019年前端面试大集合

158 阅读11分钟

只写给自己看

JavaScript

1. js继承的几种方式及优缺点

参考链接:微信 参考链接:阮一峰
方法一 原型链继承

原型链的基本原理:每个构造函数都有一个原型对象,原型对象有一个指向构造函数的指针。实例有一个指向原型的指针。如果一个原型对象等于另一个构造函数的实例,那么这个原型对象就有一个指向另一个原型的指针,另一个原型又有指向另一个构造函数的指针。

picture

方法二 借用构造函数继承

方法三 组合式继承

方法四 ES6 class 继承

picture

2.事件流、事件代理

当鼠标点击某个节点时,出发click事件,事件的捕获阶段最先开始,从document节点开始逐渐向下传播,直到被点击的节点,事件进入目标阶段,在目标阶段之后,之间由目标节点开始事件的冒泡阶段,直到document节点为止。整个事件流可以通过调用事件的stoppropagation方法停止事件的传播过程。

事件冒泡:事件开始时是最具体的元素接收,然后逐级向上传播到最不具体的节点(文档)。

事件捕获:不太具体的节点更早接受到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。

事件代理就是事件委托,利用事件冒泡的原理实现。在父节点上注册事件,当某个字节点的点击事件被触发时,事件会逐层冒泡到最上层,即这个 父元素,因为已经被注册了事件,事件被触发。委托它们的父级代为执行。只指定一个事件处理程序,就可以管理某一类型的所有事件。例如click事件会冒泡到document层次。

3.防抖和节流

防抖和节流都是为了解决短时间内大量触发某函数而导致的性能问题。

  • 节流:如果持续触发事件,每隔一段时间,只执行一次事件。
  • 防抖:在一个事件触发完后又触发了这个事件,就以新的事件的时间为准,n秒后才执行。总之就是等触发完事件n秒内不再触发事件,才执行,就是这么任性。

4.setTimeout输出0-9问题

    for (var i = 0; i< 10; i++){
    	 setTimeout(() => {
    		 console.log(i);
        }, 1000)}

方法一:利用setTimeout函数的第三个参数,作为回调函数的第一个参数传入

    for (var i = 0; i < 10; i++) {
      setTimeout(i => {
        console.log(i);
      }, 1000, i)}

方法二:利用let变量的特性-let声明的变量会在在当前块级作用域里创建一个文法环境

    for (let i = 0; i < 10; i++) {
      setTimeout(() => {
        console.log(i);
      }, 1000)}

方法三:利用函数自执行的方式,把当前for循环中的i传递过去,构建出块级作用域。

    for (var i = 0; i < 10; i++) {
      (i => {
        setTimeout(() => {
          console.log(i);
        }, 1000)
      })(i)}

方法四:利用try/catch形成的块级作用域

    for(var i = 0; i < 10; i++){ 
      try{
         throw i;
      }catch(i){
         setTimeout(() => { console.log(i); },1000)    
      }}       

5.new关键字

要创建新实例必须使用new关键字。以这种方式调用构造函数会经历以下4个步骤:
1)创建一个新对象;
2)将构造函数的作用域赋给新对象(此时this就指向了这个新对象);
3)执行构造函数中的代码(为这个新对象添加属性);
4)返回新对象。

7.ES6箭头函数

箭头函数使用的几点注意:
1.箭头函数的this,指向的是定义时所在的对象,而不是使用时所在的对象。
2.不能把箭头函数当作构造函数,也就是说,不能使用new命令,否则会报错。
3.不能在箭头函数中使用arguments对象,该对象在函数体内不存在,可以使用rest参数代替。
4.不可以使用yield命令,因此箭头函数不能用作 Generator 函数
tips:this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。 也就不能用call()、apply()、bind()这些方法去改变this的指向。

网络

6.缓存

前端缓存 浅谈http缓存

6.1强缓存

请求资源不会向服务器发送请求,直接从缓存中获取,状态码200后面跟着from disk cache或者from memory cahce关键字。

Expires:值为服务端返回的到期时间。如果在时间内,直接使用缓存数据。但是客户端时间和服务端时间可能存在误差。

Cache-Control:max-age,

Cache-Control优先级高于Expires。

6.2 协商缓存

向服务器请求资源时,浏览器与服务器通过一个值作为更新flag,用作协商和判断。

Etag/If-None-Match:首次请求时服务器端返回的资源唯一标识/再次请求时浏览器通知服务器上次返回的资源唯一标识。如果标识发生了变化,就把资源返回给浏览器(返回值200)并缓存,如果资源未发生变化就返回浏览器304(未修改),浏览器使用本地缓存。

Last-Modified/If-Modified-Since:首次请求时服务器返回的资源最后修改时间/再次请求时浏览器通知服务器上次请求时返回的资源最后修改时间。

Etag优先级高于Last-Modified。

6.3 memory cache(内存缓存)和disk cache(磁盘缓存)

memory cache:kill进程后,也就是浏览器关闭后,数据将不存在。只能缓存派生资源。

disk cache:kill进程后,数据仍然存在。只能缓存派生资源。

三级缓存原理:

1.请求加载资源时,先根据资源的http header判断是否命中强缓存;
1.1 如果命中,先去内存缓存看,如果有所需数据,直接加载,状态码200;
1.2 如果内存没有,就去磁盘获取,如果有所需数据,直接加载,状态码200;
2. 如果强缓存没有命中,浏览器会发送请求到服务器,服务器根据资源的另外一些http header验证这个资源是否命中协商缓存;
2.1 如果命中,服务器将请求返回,返回304状态码,告诉客户端可以直接从缓存中加载资源;
3. 如果没有命中协商缓存,浏览器直接从服务器加载资源并缓存,状态码200。

6.4 用户行为多浏览器缓存的控制
  • 地址栏访问:浏览器跳转是正常用户行为,将会触发浏览器缓存机制。
  • F5刷新:浏览器会设置max-age=0,跳过强缓存,进行协商缓存判断。
  • ctrl+F5:跳过强缓存和协商缓存,直接从服务器拉取资源。

浏览器

1.浏览器的渲染过程

参考链接

picture

  • 浏览器渲染过程:

    1)解析HTML,生成DOM树,解析CSS,生成CSSOM树;

    2)将DOM树和CSSOM树结合,生成渲染树(Render tree);

    3)Layout(回流):根据生成的渲染树,进行回流,其实就是布局,得到节点的几何信息(位置、大小)。计算节点在设备视口(viewport)内的确切位置和大小。

    4)重绘:根据渲染树以及回流得到的几何信息,将渲染树的每个节点都转换为屏幕上的实际像素

    5)Display:将元素发送给GPU,展示在页面上。

  • 生成渲染树

picture
构建渲染树的过程中,浏览器完成的工作:

1)从DOM树的根节点开始遍历每一个可见节点

2)对于每个可见节点,找到CSSOM树中对应的规则,并应用它们;

3)根据每个可见节点以及其对应的样式,组合生成渲染树。

不可见的节点包括:1.一些不会渲染输出的节点,比如script、meta、link等。2.一些通过css进行隐藏的节点,不如display:none。(利用visibility和opacity隐藏的节点还是会显示在渲染树上)。
注意:渲染树只包含可见节点。

2.重绘和回流(repaint&reflow),如何进行优化(未完成)

  • 回流:计算节点在设备视口(viewport)内的确切位置和大小的阶段。 为了弄清每个对象在网站上的确切大小和位置,浏览器从渲染树的根节点开始遍历。

  • 重绘:将渲染树上的每一个节点转换到设备屏幕上的实际像素。

  • 何时发生回流重绘?
    当页面布局和几何信息发生变化时,就会回流,比如:

    ① 添加或删除可见的DOM元素

    ② 元素的位置发生变化

    ③ 元素的尺寸发生变化(外边距、内边框、边框大小、高度和宽度等)

    ④ 内容发生变化,如文本变化或图片被另一个不同尺寸图片替代

    ⑤ 页面一开始渲染的时候

    ⑥ 浏览器的窗口尺寸变化(回流根据视口的大小来计算元素的位置和大小)

  • 浏览器的优化机制

  • 减少回流和重绘的方法

RenderLayers :渲染层

GraphicsLayers:图形层

Composite Layers:合成层

居中为什么用transform,而不是margin top/left,下面的文章里会涉及浏览器渲染原理

改变margin会改变render tree的结构,会引起页面layout repaint和回流。使用transform会形成一个单独的composite layer(合成层),它所引起的paint只会发生在这个合成层中,不会引起整个页面的重绘回流。

css

1.css选择器权重

权值等级划分为4个等级:

第一等级:内联样式,如style,权值为1,0,0,0;

第二等级:ID选择器,如#id=””,权值为0,1,0,0;

第三等级:class|伪类|属性 选择器,如.class|:hover,:link,:target|[type],权值为0,0,1,0;

第四等级:标签|伪元素 选择器,如p|::after,::before,::first-inline,::selection,权值为0,0,0,1。 通用选择器(*),子选择器(>),相邻同胞选择器(+)等不在4个等级之内,权值为0,0,0,0。

2.文档流

2.1原理

文本流,position属性可以将元素从文本流脱离出来显示。

css中元素有3种定位机制:

  • 文档流(normal flow)包括块级元素的块级格式和行内元素的行内格式以及两种元素的相对定位方式。
  • 浮动
  • 绝对定位

2.2脱离文档流

脱离文档流是将元素从普通布局排版中拿走,其他盒子在做定位时,会当作脱离文档流的元素不存在而进行定位。

2.3浮动

原理
当float引起元素脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在其周围。而absolute positioning引起元素脱离文档流时,其他盒子与其他盒子内的文本都会无视它。 浮动元素碰到包含它的元素的边框或者其他浮动元素的边框会停留下来。
浮动元素会引起的问题:
因为脱离了文档流,会出现塌陷的情况。

(1)父元素的高度无法撑开,影响与父元素的同级元素。

(2)与浮动元素同级的非浮动元素(内联)会跟随其后。

(3)若非第一个元素浮动,则该元素之前的元素也要跟随其后,否则会影响页面显示的结构。

消除浮动的方法:

(1)创建BFC元素,包裹浮动元素,从而闭合浮动。

BFC计算高度时,浮动元素也会参与计算。BFC是一个独立的盒子。

(2)给浮动元素的父元素加一个空元素,clear属性用于清除浮动。after伪元素也是通过在元素后面生成内容为一个点的块级元素。

.outer(:after) {
    clear: both; 
    content: ''; 
    display: block; 
    height: 0; 
    width: 0;
}

3.延伸阅读-CSS布局概念

CSS布局概念

4.居中div,垂直水平居中

    margin是相对于父元素,transform是相对于自身。
4.1固定宽高

1)定位+margin

lement.style{
    position:absolute; 
    left:50%; 
    top:50%; 
    margin-left:-250px; 
    margin-top:-250px; 
    width:500px; 
    height: 500px; 
}

2)定位+transform

element.style {
    position: absolute; 
    left: 50%; 
    top: 50%; 
    width: 500px; 
    height: 500px; 
    transform: translate3d(-50%, -50%, 0);
}
4.2不固定宽高 不定宽高的方法基本都适用于固定宽高的方法。

1)定位+transform

2)弹性布局 但改变父元素的display值

div.parent{ display: flex; }  div.child{ margin: auto }
div.parent{ display: flex; justify-content: center; align-items: center;  } 

3)网格布局

div.parent{ display: grid; }  
div.child{ justify-self: center; align-self: center; }

5.BFC

BFC就是块级格式上下文,是页面盒模型布局中的一种CSS渲染模式,相当于一个独立的容器。里面的元素和外部的元素相互不影响。创建BFC的方式有:

  1. html根元素
  2. float浮动
  3. 绝对定位
  4. overflow不为visible
  5. display为表格布局或弹性布局