高级Web前端必会面试题知识点,不断更新中。。。

高级Web前端工程师必会面试题,这里只是整理一些范围知识点,并没有特别具体的面试题目,只要把这些知识点搞明白了,面试题都不是问题。
文档持续更新中。。。加油骚年!!

布局的三种模式

参考:https://www.cnblogs.com/Renyi-Fan/p/12173366.html#_label3

  • 弹性盒布局 flex
    盒子是并列的,可以设置指定宽度,轻松实现两栏,三栏布局,经典的圣杯布局和双飞翼布局就是通过flex来实现的。
    但是,flexbox 布局方式对浏览器的支持不太友好,有一些兼容性问题,但是,这应该是未来发展的趋势。

  • 浮动 float浮动
    float布局是目前各大网站用的最多的一种布局方式了。
    通过给元素设置float属性来实现元素浮动,浮动的元素是脱离文档流的,但是不脱离文本流。
    特点:
    1) 对自身:a、float元素可以形成块,可以让行内元素变成块元素,也拥有宽和高;b、浮动元素的位置尽量靠上;c、设置float:left 或 float:right,如果这一行满足不了浮动元素的宽度,则会被挤到下一行。
    2) 对兄弟:a、不影响其他块元素的位置;b、影响其他块元素的文本
    3) 对父元素:高度塌陷
    高度塌陷:(解决方案)

  • 响应式
    最简单的方式是加上一个 meta 标签, ,其中 width = device-width 这一句的意思是让页面的宽度等于屏幕的宽度。
    rem 是指html的font-size的大小, 根据rem来计算各个元素的宽高,然后在配合media query 就可以实现自适应
    @media query 语法

1  @media screen and (max- 360px) {
2       html { font-size: 12px; }
3  }
移动端布局适配设备的方案

参考https://www.cnblogs.com/liuXiaoDi/p/12261100.html

  • rem
    rem 以根元素字体大小作为参照的布局方式,可以实现等比缩放布局,不管内容是多大的,显示的内容是一样的。
  • %
    页面宽度为100%,高度固定,当屏幕越大,显示的内容也就越多。
    控件弹性,图片等比例缩放,文字流式
1px边框的解决方案
  • 原理:
    在高分辨率的显示屏中,像素比为2或者3,1px边框看起来比真实的1px边框看起来更宽
  • 方案
    1. 使用伪类添加transform:元素本身不定义边框,给伪元素定义一个 1px 边框,并且根据像素比值(dpr => device-pixel-ratio)设置缩放比例
    当 dpr > 2.5 时设置 scale(0.333),
    当 2.49 > dpr > 1.5 时设置 scale(0.5),
    当 dpr < 1.49 时设置 scale(1)
    2. 图片 border-image
BFC(Block Formatting Contexts)

文档:day0220–BFC.note
链接:http://note.youdao.com/noteshare?id=f0a95534319d2cd8f49dbe9b6f5240eb&sub=B77453B2104943B09697AF70C4CE68A5

  • 概念
    BFC:块级格式化上下文
  • 触发条件
    1. 根元素 html
    2. float的值不为none
    3. overflow的值不为visible
    4. display的值为inline-block/table-cell/table-caption/flex/inline-flex
    5. position 的值为 absolute 或者 fixed
  • 特性
    1. box垂直方向的距离由margin决定,属于同一个BFC的两个相邻box的margin会发生重叠
      解释margin上下会重叠,以及解决方法的原因
      解决方法:给第二个box添加一个父元素,并且添加overflow: hidden;属性,使这两个box分属两个不同的BFC,即可解决margin重叠的问题。
    2. 计算BFC高度时,浮动元素也参与计算
      解析高度塌陷 可以用 overflow: hidden解决
    3. BFC的区域不会与float box发生重叠
    4. BFC内部的box会在垂直方向一个接一个的放置
    5. 每个元素的margin的左边会与包含块border的左边相接触,即使存在浮动也会如此
    6. BFC就是页面上的一个独立容器,容器里面的元素不会影响到外面的元素
BootStrap布局原理
  • Bootstrap 是一个用于快速构建Web应用程序和网站的前端框架,是基于html、css、js。
  • 栅格布局:
    Bootstrap 内置了一套响应式、移动设备优先的流式栅格系统,会随着屏幕设备或者视口(Viewport)尺寸的增加,系统会自动分为最多12列。
    网格系统的实现原理也是非常简单的,只需要通过定义容器的大小,然后平分12份(也有24,32的,但是12是最常见的),再调整内外边距,最后结合媒体查询,就可以实现了这种栅格布局系统。
  • 优点:自适应布局,友好的移动端布局
  • 缺点:不兼容IE,需要修改bootstrap的样式
  • 相关问题:
    • 分辨率:xs(超小屏幕手机 < 780px)、sm(小屏幕平板 >= 780px)、md(中等屏幕桌面显示器 >= 992px)、lg(大屏幕大桌面显示器 >= 1200px)
    • bootstrap 栅格还有24格的 要怎么设置:分别在十二的基础上嵌套,每个嵌套一个!
    • container 与 container-fluid 有什么区别:container是文本居中、container-fluid占整行
Sass/Less/Stylus/StyledComponents 区别,联系,在什么场景下使用
  • CSS预处理器(Sass/less/stylus):就是一种专门的编程语言,为css增加一些编程的特性,将css作为目标生成文件,然后就可以使用这种语言进行编程。可以让代码更加简洁、适应性更强、可读性更强、易于代码的维护。
  • 样式化组件(StyledComponents):
  • 区别与联系:
    1. Sass与Less语法较为严谨,Stylus语法比较散漫,Less上手比较快
    2. Sass和Less相互影响比较大,Sass已经全面兼容css
    3. Sass和Less都有第三方工具提供转译,特别是Sass和Compass是绝配
    4. Sass、Less和Stylus都具有变量、作用域、混含、嵌套、继承、运算符、颜色函数、导入和注释等基本特性,各自特性实现功能基本类似,只是使用规则有所不同
    5. Sass和Stylus具有类似的语言处理能力,比如条件语句、循环语句等,而Less需要通过when等关键词模拟这些功能
  • 使用场景:
    • Sass:在编写代码时,需要用到变量、嵌套、混合、导入等高级操作时,可以更好的组织管理样式文件,更高效的开发项目。
    • Less:它更适用于皮肤、模板等整体框架固定死的网站制作,比如论坛、空间
    • Stylus:可编程
    • StyledComponents:在React中使用,编写实际的css代码来设计组件样式,不需要组件和样式之间的映射,创建成功后就是一个React组件

JavaScript 系列

变量对象+作用域链+this(执行上下文)
  • 变量对象:如果变量与执行上下文相关,那变量自己应该知道它的数据存储在哪里,并且知道如何访问,这种机制就是变量对象(VO)。
    变量对象是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的变量、函数声明、函数形参等内容。
  • 全局对象:是在进入任何执行上下文之前就已经创建了的对象。
    全局对象只存在一份,它的属性在程序中任何地方都可以访问,全局对象的生命周期终止于程序退出那一刻。
  • 作用域链与原型链:
    • 区别:
      1.作用域链是对于变量而言,原型链是对于对象的属性。
      2.作用域链顶层是window,原型链顶层是Object
    • 联系:从链表开始查找,直到找到为止。
  • this指向:取决于被调用的方式
    1. 如果普通的函数调用,非严格模式下,this指向window,严格模式下,this是undefined
    2. 如果是对象调用的方式,this指向该对象
    3. 如果是call()、apply()或者bind()方式调用,this指向被绑定的对象
    4. 如果是构造函数调用方式,this指向实例化出来的新对象
    5. 如果是箭头函数,是根据当前的词法作用域来决定this,具体来说,箭头函数会继承外层函数调用的this绑定
闭包
  • 闭包:就是能够读取其他函数内部变量的函数
  • 变量的作用域分为全局变量和局部变量两种。而js中的函数内部可以直接读取全局变量,但是函数外部无法读取函数内部的局部变量。如果想要取得函数内部的变量,就要在函数的内部再定义一个函数,将函数作为返回值返回,就可以在函数的外部读取他的内部变量了。
  • 闭包的作用:
    1. 可以读取函数内部的变量
    2. 让这些变量的值始终保存在内存中 => 可能导致内存泄漏
  • 闭包的this指向:外部函数的this指向调用他的对象,内部函数的this指向了全局对象。
原型
  • 原型(__proto__对象属性):原型为同一个构造函数new出来的实例对象提供了一个公共的区域来存放共同的属性和方法。
    js规定,每一个函数都有一个prototype对象属性,指向另一个对象,prototype的所有属性和方法,都会被构造函数的实例继承。这就意味着,我们可以把那些不变(公共)的属性和方法,直接定义在 prototype对象属性上。prototype就是调用构造函数所创建的那个实例对象的原型。
    prototype可以让所有的对象实例共享它所包含的属性和方法。也就是说,不必再构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。
  • 为什么要使用原型:可以节省一定的内存,特别是需要构建多个实例的时候。
  • 原型链:实例对象与原型之间的连接,叫做原型链。
    js在创建对象的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype。
  • 内部原型(proto)和构造器原型(prototype)
    1. 每个对象都有一个proto属性,原型链上的对象正是依赖这个属性连结在一起。
    2. 作为一个对象,当访问其中的一个属性或者方法的时候,如果这个对象中没有这个方法或属性,那么js引擎将会访问这个对象的proto属性所指向的上一个对象,并在那个对象中查找指定的方法或属性,如果不能找到,那就会继续通过这个对象的proto属性指向的对象进行向上查找,直到这个链表结束。
继承
  • 前提:提供父类(继承谁,提供谁的属性)
  • 分类:
  1. 原型链继承:可以让新实例的原型等于父类的实例
    • 特点:实例可继承的属性有:实例的构造函数的属性、父类构造函数属性、父类原型的属性。(新实例不会继承父类实例的属性)
    • 缺点:1. 新实例无法向父类构造函数传参
      2. 继承单一
      3. 所有新实例都会共享父类实例的属性(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改)
  2. 构造函数继承:用.call().apply()将父类构造函数引入子类函数(在子类函数中做了父类的复制)
    • 特点:1. 只继承了父类构造函数的属性,没有继承父类原型的属性
      2. 解决了原型链继承的缺点
      3. 可以继承多个构造函数属性(call多个)
      4. 在子实例中可以向父实例传参
    • 缺点:1. 只能继承父类构造函数的属性
      2. 无法实现构造函数的复用(每次用都要重新调用)
      3. 每个新实例都有父类构造函数的副本
  3. 组合继承(原型链继承+构造函数继承):结合了两种模式的优点,传参和复用
    • 特点:1. 可以继承父类原型上的属性,可以传参,可复用
      2. 每个新实例引入的构造函数属性是私有的
    • 缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
  4. 原型式继承:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了一个可以随意增添属性的实例或对象,Object.create()就是这个原理
    • 特点:类似于复制一个对象,用函数来包装
    • 缺点:1. 所有实例都会继承原型上的属性
      2. 无法实现复用(新实例属性都是后面添加的)
  5. 寄生式继承:就是给原型式继承外面套个壳子
    • 特点:没有创建自定义类型,因为只是套了个壳子返回对象,这个函数就成了创建的新对象。
    • 缺点:没有用到原型,无法复用
  6. 寄生组合继承:(常用)修复了组合继承的问题
    寄生:在函数内返回对象然后调用
    组合:1. 函数的原型等于另一个实例;2. 在函数中用apply或者call引用另一个构造函数,可传参
函数节流和防抖
  • 函数的节流和防抖是优化高频率执行js代码的一种手段,js中的一些事件在执行触发时,会不断调用 绑定在事件上的回调函数,极大的浪费资源,降低性能。为了优化体验,需要对这类事件进行调用次数的限制,此时引入函数节流防抖。
  • 节流(throttle):控制事件发生的频率,比如控制为1s发生一次,甚至1分钟发生一次。
    • 应用场景:
      1. scroll事件,滚动监听事件,每隔一段时间计算一次位置信息等
      2. 浏览器的播放事件,每隔1s计算一次进度信息
      3. input框实时搜索并发送请求展示下拉列表,每隔1s发送一次请求。(防抖也可以)
      4. 高频点击提交,表单重复提交
    • 代码实现:
 1  function throttle(fn, delay) {
 2      let timer;
 3      return function () {
 4          let _this = this;
 5          let args = arguments;
 6          if (timer) {
 7              return;
 8          }
 9          timer = setTimeout(function () {
10              fn.apply(_this, args);
11              timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
12          }, delay)
13      }
14  }
  • 防抖(debounce):防止抖动,以免把一次事件误执行多次,影响性能。
    • 应用场景:
      1. 登录注册、发短信等按钮避免用户点击过快,导致多次发送请求,需要防抖
      2. 调整浏览器窗口大小时,resize次数过于频繁,造成计算过多,此时需要一次到位,需要防抖
      3. 文本编辑器实时保存,无任何更改操作一段时间后自动保存
      4. mousemovemouseover鼠标移动事件防抖
      5. 搜索框搜索输入,只需要用户最后一次输入完,在发送请求防抖
      6. 手机号、邮箱验证输入检测
    • 代码实现:
 1  function debounce(fn, delay) {
 2             let timer; // 维护一个 timer
 3             return function () {
 4                 let args = arguments;
 5                 if (timer) {
 6                     clearTimeout(timer);
 7                 }
 8                 timer = setTimeout(()=> {
 9                     fn.apply(this, args); // 用apply指向调用debounce的对象,相当于this.fn(args);
10                 }, delay);
11             };
12         }
  • 比较:
    • 相同点:
      1. 都可以通过使用 setTimeout 实现
      2. 目的都是为了降低回调执行频率,节省计算资源
    • 不同点:
      1. 函数防抖:在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。
      2. 函数节流:在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用它来提高性能。
      3. 函数防抖关注一定时间连续触发的事件只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
  • 总结:
    防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout。防抖可以比作等电梯,只要有人进来,就需要再等一会。业务场景有避免触发按钮多次重复提交。
    节流:控制流量,单位时间内事件只能触发一次。代码实现重在开锁关锁 timer=timeout;timer=null。节流可以比作红绿灯,每等一个红灯时间就可以过一批。
函数柯里化与反柯里化
  • 柯里化(currying):是一种编程技术,主要就是把原本接收多个参数的函数变成只接受一个参数的函数,并且返回一个接收剩余参数的函数。
    • 应用场景:
      1. 封装一些含有环境判断的方法时,函数柯里化可以帮助我们减少判断条件执行的次数;
      2. 在封装函数节流、防抖、bind此类返回值是函数的方法时,会用到函数柯里化;
      3. 可用与 vue、react、小程序中的事件传参,在事件绑定时就执行回调函数传参,根据传参值返回真正的事件 callback函数。
  • 反柯里化:扩大方法的适用范围。
    1. 可以让任何对象拥有其他对象的方法(改变原来方法上下文)
    2. 增加被反柯里化方法接收的参数

设计模式

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。

  1. 工厂模式
    工厂模式定义了一个用于创建对象的接口,用户只负责传递需要的参数,不需要关心内部的逻辑,隐藏了创建实例的复杂度,最后返回一个实例。
  2. 单例模式
    单例模式是指在内存中只会创建且仅创建一次对象的设计模式。单例模式很常用,比如全局缓存、全局状态管理等,这些只需要一个对象,就可以使用单例模式。比如 Redux、Vuex的store。
  3. 观察者模式(发布-订阅模式)
    观察者模式中一般都需要实现三个接口: subscribe()接收观察者,使其订阅;unsubscribe()取消订阅;fire()触发事件,通知到所有观察者。
  4. 装饰器模式
    装饰器模式不需要改变已有的接口,它的作用是给对象添加功能。比如 react里的高阶组件。
  5. 适配器模式
    适配器用来解决两个接口不兼容的问题,不需要改变已有的接口,通过包装一层的方式实现两个接口的正常协作。我们其实经常使用到适配器模式。比如父组件传递给子组件一个属性,组件内部需要使用 computed计算属性来做处理,这个过程就用到了适配器模式。
ES6新增API(Proxy, Reflect, Promise, Generator, async, Decorator, Class)
  • Proxy:用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。这个词的原理为代理,在这里可以表示由它来“代理”某些操作,译为“代理器”。

    • 基本用法:ES6原生提供给了Proxy构造函数,用来生成Proxy实例。
      var proxy = new Proxy(target, handler);
      
      Proxy对象的所有用法,都是通过这种形式。不同的只是handle参数的写法。其中new Proxy用来生成Proxy实例,target是表示所要拦截的对象,handle是用来定制拦截行为的对象。
  • Reflect:是一个全局的普通的对象,原型是Object。

    • 目的:
      1. 将Object对象的一些属于语言内部的方法放到Reflect对象上,从Reflect上能拿到语言内部的方法。如:Object.defineProperty;
      2. 修改某些object方法返回的结果。如:Object.defineProperty(obj, name, desc)在无法定义属性的时候会报错,而Reflect.defineProperty(obj, name, desc)则会返回false;
      3. 让Object的操作都变成函数行为。如object的命令式:name in obj和delete obj[name] 则与 Reflect.has(obj, name)、Reflect.deleteProperty(obj, name)相等;
      4. Reflect对象的方法与Proxy对象的方法一一对应,只要proxy对象上有的方法reflect也能找到。
  • Promise:是一个专门解决异步回调地狱的问题。

    • 所谓 Promise,简单点来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,promise是一个对象,它可以从获取异步操作的消息,promise提供了统一的API,各种异步操作都可以用同样的方法进行处理。

      • 特点:
      1. 对象的状态不受外界影响,promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)、rejected(失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
      2. 一旦状态改变就不会再变,任何时候都可以得到这个结果,promise对象的状态改变,只有两种可能:从 pending => fulfilled,从pending => rejected。这个就称为 resolved。如果改变已经发生,再对 promise 对象添加回调函数,也会立即得到这个结果,这与事件(event)完全不同,事件的特点是:如果你错过了它,再去监听是得不到结果的。
      • 用法:
      1. Promise 是一个构造函数,这个构造函数有两个参数,分别是 resolve(成功之后的回调函数)和 reject(失败之后的回调函数)
        因为 Promise 表示的是一个异步操作,每当我们 new 一个 promise 实例,就表示一个具体的异步操作,那么这个异步操作的结果就只能有两种状态:成功/失败,两者都需要回调函数 resolve/reject返回。所以内部拿到操作结果后,无法使用 return 把操作结果返回给调用者,这个时候只能用回调函数的形式来吧成功或者失败的结果返回给调用者。
      2. promise 实例生成以后,可以用 then方法分别指定 resolved 状态和 rejected 状态的回调函数,then方法可以接收两个回调函数作为参数,第一个回调函数是 promise 对象的状态变成 resolved 时调用,第二个回调函数是 promise 对象的状态变为 rejected 时调用。第二个回调函数是可选的,这两个函数都接受 promise 对象传出的值作为参数。
  • Generator:与平常的函数不同,它可以理解为是一个分布执行的函数,返回值是一个遍历器。

    • 用法:
      1. 外部可以通过next(),thow()和return()调用,只是调用的形式不同。
      2. 在应用方面主要是异步调用,不同于以前的回调函数和Promise(Promise算是对回调函数解决嵌套繁琐问题提出的)
      3. 它在每一个yield中部署自己的异步操作,等到需要执行的时候再调用。
      4. generator函数和Ajax可以一起进行同步操作。
      5. 它的分布执行的特性决定了它对耗时大的多步操作有很大的改进(generator如果你不执行,那之后的程序系统不会编译)。
      6. 部署Iterator接口:generator函数可以再任何对象上部署Iterator接口。
  • async/await:回调地狱的终极解决方案,使用它可以把异步代码写的看起来像同步代码。

    • await 是一个函数中的关键字,要求函数必须是 async 声明的函数。当 await 中的方法执行完毕或者返回后执行后续代码。
  • Decorator:修饰器,是一个函数,用来修饰类的行为。不过目前主流浏览器都没有很好的支持,我们需要用babel来转换为浏览器能识别的语言。

    • 装饰器在javascript 中仅仅可以修饰类和属性,不能修饰函数。
    • 装饰器对类的行为的改变,是代表编译时发生的,而不是在运行时。
    • 装饰器能在编译阶段运行代码。
    • 装饰器是经典的AOP模式的一种实现方式。
    • 执行顺序:同一处的多个装饰器是按照洋葱模型,由外到内进入,再由内到外执行。
  • Class:类,通过class关键字可以定义类。

    • class 关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。
    • 注意:
      1. 在类中声明方法的时候,千万不要给该方法加上 function 关键字
      2. 方法之间不要用逗号分割,否则会报错
    • 用法:
      1. 类自身指向的就是构造函数,所以可以认为 ES6 中的类其实就是构造函数的另一种写法。
      2. 类的所有方法都定义在类的prototype属性上,也可以通过prototype属性对类添加方法。
      3. 可以通过 Object.assign() 来为对象动态增加方法。
      4. constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。
      5. constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。
      6. 类的所有实例共享一个原型对象,他们的原型都是 Person.prototype,所以proto属性是相等的。
      7. class不存在变量提升,所以需要先定义再使用。
浏览器渲染页面的过程

https://www.jianshu.com/p/b6b42fd3f80e

  • 浏览器从服务器那收到的HTML,CSS,JavaScript等相关资源,然后经过一系列处理后渲染出来的web页面。

  • 过程:

    1. 浏览器将获取的HTML文档并解析成DOM树。
    2. 处理CSS标记,构成层叠样式表模型CSSOM(CSS Object Model)。
    3. 将DOM和CSSOM合并为渲染树(rendering tree)将会被创建,代表一系列将被渲染的对象。
    4. 渲染树的每个元素包含的内容都是计算过的,它被称之为布局layout。浏览器使用一种流式处理的方法,只需要一次pass绘制操作就可以布局所有的元素。
    5. 将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting。

    以上五个步骤并不一定一次性顺序完成,比如DOM或CSSOM被修改时,亦或是哪个过程会重复执行,这样才能计算出哪些像素需要在屏幕上进行重新渲染。而在实际情况中,JavaScript和CSS的某些操作往往会多次修改DOM或者CSSOM。

浏览器缓存(强缓存,协商缓存)
  • 缓存:就是一个资源副本,当我们向服务器请求资源后,会根据情况将资源copy一份副本存在本地,方便下次读取。缓存最根本的作用是减少没必要的请求,使用缓存可以减少时长,从而优化用户体验,减少流量消耗,减轻服务器的压力。
  • 强缓存:直接从本地副本比对读取,不去请求服务器,返回的状态码是 200(expires 和 cache-control)
  • 协商缓存:会去服务器比对,若没改变才直接读取本地缓存,返回的状态码是 304(last-modified 和 etag)
  • 获取缓存的流程:
    1. 先根据这个资源的 http header 判断它是否命中强缓存,如果命中,则直接从本地缓存中获取资源,不会则向服务器请求 资源。
    2. 当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些request header验证这个资源是否命中协商缓存,这个过程成为http再验证,如果命中,服务器直接返回请求而不返回资源,而是告诉客户端之间从缓存中获取,客户端收到返回后就直接从客户端获取资源。
    3. 强缓存和协商缓存的共同之处在于:如果命中缓存,服务器不会返回资源;区别是:强缓存不发送请求打服务器,但是协商缓存会发送请求到服务器。
    4. 当协商缓存没有命中时,服务器会返回资源给客户端。
    5. 当ctrl+F5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存。
    6. 当F5刷新页面时,跳过强缓存但会检查协商缓存
浏览器端 Event loop

https://segmentfault.com/a/1190000018181334

  • 事件循环(event-loop):主线程从"任务队列"中读取执行事件,这个过程是循环不断的,这个机制被称为事件循环。此机制具体如下:主线程会不断从任务队列中按顺序取任务执行,每执行完一个任务都会检查microtask队列是否为空(执行完一个任务的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去任务队列中取下一个任务执行。
  • 什么需要:因为JavaScript是单线程的。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。为了协调事件(event),用户交互(user interaction),脚本(script),渲染(rendering),网络(networking)等,用户代理(user agent)必须使用事件循环(event loops)。
webpack 细节
  • webpack中在使用babel插件处理js代码的时候,为什么使用polyfill,如何使用polyfill?
    • 原因:因为在使用preset_env 处理js代码时,无法将所有的ES6的语法全部转换成ES5语法,就比如promise、array.from以及实例方法都无法转换,这个时候需要加入垫片。
    • 使用:
      1. 在入口文件引入@babel/polyfill ,会污染全局环境
      2. 在配置文件中的entry中写 ,也会污染全局环境
      3. 可以配置@babel/preset-env useBuiltIns接收3个参数
      entry:不管代码 有没有用到,只要目标浏览器不支持的都会引入对应的polyfill;自动引入polyfill模块;
      usage: 根据代码的使用情况,按需引入;自动引入polyfill模块;
      false:不会自动引入polyfill模块;
      4. corejs 3.0以后的版本; 如果参数为entry,则需要在入口文件中引入两个包
webpack 和 gulp 的区别
  • webpack是一个模块打包器,强调的是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源都看成是模块,通过loader和plugin对资源进行处理。
  • gulp是一个前端自动化构建工具,强调的是前端开发的工作流程,可以通过配置一系列的task,第一task处理的事情(如代码压缩,合并,编译以及浏览器实时更新等)。然后定义这些执行顺序,来让glup执行这些task,从而构建项目的整个开发流程。自动化构建工具并不能把所有的模块打包到一起,也不能构建不同模块之间的依赖关系。
webpack 从启动构建到输出结果经历了一系列过程
    1. 解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。
    2. 注册所有配置的插件,好让插件监听webpack构建生命周期的事件节点,以做出对应的反应。
    3. 从配置的entry入口文件开始解析文件构建AST语法树,找出每个文件所依赖的文件,递归下去。
    4. 在解析文件递归的过程中根据文件类型和loader配置找出合适的loader用来对文件进行转换。
    5. 递归完后得到每个文件的最终结果,根据entry配置生成代码块chunk。
    6. 输出所有chunk到文件系统。

文档持续更新中。。。每日更新,加油骚年!!

作者:学辉

-------------------------------------------

个性签名: 没有好看的皮囊,但有有趣的灵魂,技术没有止境!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!

原文地址:https://www.cnblogs.com/XH-jing/p/13603909.html