# 2019年07月刊

# 2019/07/22 - 2019/07/28 ⌚️


  • 最小堆和最大堆分别是什么?

    点击

    堆是一种数据结构,最小堆和最大堆,其根节点都比左右分支节点小或者是大。

  • Vue.js 中的声明式渲染是什么?

    点击

    Vue 根据状态属性值的变化自动渲染页面,隐藏了内部渲染页面的过程,这就是声明式渲染

  • console.dir() 的作用?

    console.dir 方法只会打印出对象,不会展开详细信息,当然点击之后看到的信息和前者一样。 唯一差异比较大的地方是当我们打印 HTML 文档中的节点时,会有完全不一样的表现形式。

  • 基本数据类型用栈存储,引用数据类型用堆存储。有何例外?

    例外:闭包变量是存在堆内存中的。

  • 浏览器线程与进程? (opens new window)

  • webpack 的构建流程?

    点击

    webpack 的构建流程包括 compile、make、build、seal、emit 阶段,执行完这些阶段就完成了构建过程。

    • 初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
    • 开始编译: 根据我们的 webpack 配置注册好对应的插件调用 compile.run 进入编译阶段,在编译的第一阶段是 compilation,他会注册好不同类型的 module 对应的 factory,不然后面碰到了就不知道如何处理了。
    • 编译模块: 进入 make 阶段,会从 entry 开始进行两步操作:第一步是调用 loaders 对模块的原始代码进行编译,转换成标准的 JS 代码, 第二步是调用 acorn 对 JS 代码进行语法分析,然后收集其中的依赖关系。每个模块都会记录自己的依赖关系,从而形成一颗关系树。
    • 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的* Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
    • 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
  • JavaScript 在执行时什么时候不能够自动补齐分号?

    点击
    • 下一行以中括号 “[” 开头,则当前行必须加分号。因为 JavaScript 解释器会认为这是属性访问操作,从而不会在当前行自动补齐分号导致报错。

    • 下一行以小括号 “(” 开头,则当前行必须加分号。因为 JavaScript 解释器会认为这是函数执行操作,从而不会在当前行自动补齐分号导致报错。

# 2019/07/15 - 2019/07/21 ⌚️


  • js 如何实现数组降维?

    点击
    const oldArr = [
      1,
      [2, [3], [4, 5, 6], [7, 8, 9], 10, 11],
      12,
      13,
      14,
      [15, 16, 17],
    ];
    
    const newArr = [];
    
    // 1. 递归降维
    const ergodic = arr => {
      arr.forEach(item => {
        if (Array.isArray(item)) {
          ergodic(item);
        } else {
          newArr.push(item);
        }
      });
    };
    ergodic(oldArr);
    
    console.log(newArr);
    // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ]
    
    // 2. es6 flat() 降维
    newArr = oldArr.flat(Infinity); //Infinity表示正无穷大
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
  • vue 中函数式组件的使用场景?

    点击

    函数组件是无状态的,在它们的核心中,它们只是可执行的函数,接受一些输入并根据其提供输出。

    函数式组件只是函数,所以渲染开销也低很多,这也意味着它们是非常高效的,不需要花太多时间渲染。

  • 如何快速转化为 Number 类型?

    点击
    let num = '15';
    num = +num; // 15
    
    let bool = true;
    bool = +bool; // 1
    
    1
    2
    3
    4
    5
  • JSON.parse(JSON.stringify(obj))实现深度克隆的缺点是什么?

    点击
    1. 他无法实现对函数 、RegExp 等特殊对象的克隆

    2. 会抛弃对象的 constructor,所有的构造函数会指向 Object

    3. 对象有循环引用,会报错

  • IPV6 与 IPV4 相比的优势在哪?

    点击
    • IP 地址扩大(目前 IPv4 地址不足的问题由 NAT 解决,NAT 是一种在 IP 数据包通过路由器或防火墙时重写源 IP 地址或目标地址的技术。这种技术被用于多台主机使用单个公有 IP 访问互联网的私有网络中。)

    • 包首部长度固定 40 字节,路由器不在做分片操作,直接在发送端主机分片

    • 不需 DHCP 服务器也能自动分配 IP 地址

    • 使用认证和加密功能

  • 为什么框架中更喜欢用 Object.create(null) 而不是字面量呢?

    点击

    Object.create(null)创建的对象,没有任何属性,显示 No properties,我们可以把它当作一个非常纯净的 map 来使用,我们可以自己定义 hasOwnProperty、toString 方法,不管是有意还是不小心,我们完全不必担心会将原型链上的同名方法覆盖掉。

    使用的场景:

    1. 你需要一个非常干净且高度可定制的对象当作数据字典的时候;
    2. 想节省 hasOwnProperty 带来的一丢丢性能损失并且可以偷懒少些一点代码的时候
  • HTTP 常用返回码?

    点击
    • 2XX 成功

      • 200 OK,表示从客户端发来的请求在服务器端被正确处理
      • 204 No content,表示请求成功,但响应报文不含实体的主体部分
      • 205 Reset Content,表示请求成功,但响应报文不含实体的主体部分,但是与 204 响应不同在于要求请求方重置内容
      • 206 Partial Content,进行范围请求
    • 3XX 重定向

      • 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL
      • 302 found,临时性重定向,表示资源临时被分配了新的 URL
      • 303 see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源
      • 304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况
      • 307 temporary redirect,临时重定向,和 302 含义类似,但是期望客户端保持请求方法不变向新的地址发出请求
    • 4XX 客户端错误

      • 400 bad request,请求报文存在语法错误
      • 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息
      • 403 forbidden,表示对请求资源的访问被服务器拒绝
      • 404 not found,表示在服务器上没有找到请求的资源
    • 5XX 服务器错误

      • 500 internal sever error,表示服务器端在执行请求时发生了错误
      • 501 Not Implemented,表示服务器不支持当前请求所需要的某个功能
      • 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求

# 2019/07/08 - 2019/07/14 ⌚️


  • Vue 的 nextTick 原理?

    参考文章:《全面解析 Vue.nextTick 实现原理》 (opens new window)

    参考文章: 《Vue 源码阅读 - 批量异步更新与 nextTick 原理》 (opens new window)

  • 跨标签页的通讯方式有哪些?

    参考文章:《实现多个标签页之间通信的几种方法》 (opens new window)

  • 如何从 10000 个数中找到最大的 10 个数?

    典型的 top-k 问题,参考算法题19-TOP-K 问题 (opens new window)

  • Load 和 DOMContentLoaded 事件的区别?

    点击

    Load 事件触发代表页面中的 DOM,CSS,JS,图片已经全部加载完毕。

    DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待 CSS,JS,图片加载。

  • Git 如何打标签和切换标签?

    点击
    // 附注标签
    git tag -a v1.1.0 -m 'v1.1.0 release'
    
    // 本地推送到远程
    git push origin <tag name>  // 推送一个标签到远程
    
    git push origin --tags   // 推送全部未推送的本地标签
    
    // 本地删除标签
    git tag -d <tag name>
    
    // 远程删除标签
    git push origin :refs/tags/<tag name>   // 本地tag删除了,在执行该句,删除远程tag
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • decodeURI 与 decodeURIComponent 区别 ?

    点击

    encodeURI()和 encodeURIComponent()方法可以对 URI 进行编码,以便发送给浏览器。有效的 URI 中不能包含某些字符,例如空格。而这 URI 编码方法就可以对 URI 进行编码,它们用特殊的 UTF-8 编码替换所有无效的字 符,从而让浏览器能够接受和理解。

    它们的主要区别在于,encodeURI() 不会对本身属于 URI 的特殊字符进行编码,例如冒号、正斜杠、问号和井字号;而 encodeURIComponent() 则会对它发现的任何非标准字符进行编码。

  • 取整有几种方式?

    点击
    var a = ~~2.33 // ~是按位非,就是每一位取反,~~常用来取整
    
    var b= 2.33 | 0 // 或运算
    
    var c= 2.33 >> 0
    
    
    1
    2
    3
    4
    5
    6

# 2019/07/01 - 2019/07/07 ⌚️


  • 什么是暂时性死区?

    在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”

  • 如何使用 javascript 实现枚举?

    点击
    // 可以 Object.freeze 来实现枚举,枚举对象的属性不会被改变
    var DaysEnum = Object.freeze({
      monday: 1,
      tuesday: 2,
      wednesday: 3,
    });
    
    1
    2
    3
    4
    5
    6
  • 去除 webpack 开启 dev 服务时的日志打印?

    webpack dev 配置中添加属性 stats: 'errors-only'

  • 如何获取 iframe 中的 cookie ?

  • 如何跳出 forEach 循环?

    点击

    首先,看一段代码

    var a = [1, 2, 3, 4, 5];
    a.forEach(item => {
      console.log(item); //输出:1,2
      if (item === 2) {
        //todo 想办法跳出循环
      }
    });
    
    1
    2
    3
    4
    5
    6
    7

    此时,使用 break 或者 return 并不能跳出循环,为何?foreach 编译后代码如下:

    const arr = [1, 2, 3, 4, 5];
    for (let i = 0; i < arr.length; i++) {
      const rs = (function(item) {
        console.log(item);
        if (item > 2) return false;
      })(arr[i]);
    }
    // 因此无法跳出循环
    
    1
    2
    3
    4
    5
    6
    7
    8
    1. 抛出一个错误可以结束 forEach 循环
    try {
      [1, 2, 3, 4, 5].forEach(function(item) {
        if (item === 2) throw item;
        console.log(item);
      });
    } catch (e) {}
    
    1
    2
    3
    4
    5
    6
    1. 使用 splice 或 array.length

    已删除的项不会被遍历到。如果已访问的元素在迭代时被删除,之后的元素将被跳过。因此我们可以用 length 或 splice 来修改数组

    var arr = [1, 2, 3, 4, 5];
    arr.forEach((item, index) => {
      console.log(item);
      if (item === 2) {
        arr.length = index;
      }
    });
    
    1
    2
    3
    4
    5
    6
    7

    直接修改数组的 length, 原数组便发生了更改,有时候我们并不要这种更改,因此我们可以使用一个小技巧,即将数组从 0 开始截断,然后重新赋值给数组也就是 array=array.splice(0)

    var arr = [1, 2, 3, 4, 5];
    arr.forEach((item, index) => {
      console.log(item);
      if (item === 2) {
        arr = arr.splice(0);
      }
    });
    // 数组被清空后又将删除的元素数组赋值给原数组,因此原数组没有变化且跳出了循环
    
    1
    2
    3
    4
    5
    6
    7
    8
  • IP 地址和 Mac 地址有什么区别?

    点击

    IP 地址是逻辑上的,用户可以修改自己设备的 IP 地址,Mac 地址是物理上的,直接烧入物理设备,比如路由器,用户不能轻易修改。

    IP 地址负责标记发送方和接收方,而 MAC 地址负责传输过程中的分段传送,二者缺一不可。

  • UDP 和 TCP 相比有何不同?

    点击

    UDP 是一个简单的传输层协议。和 TCP 相比,UDP 有下面几个显著特性:

    • UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
    • UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
    • UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
    • UDP 支持多播和广播。