JavaScript 核心
经典概念
javascript 有哪些原始类型
Undefined,Null,Boolean,Number,String,Symbol,Bigint (一项新的提案让这个答案可能增加 Record 和 Tuple 这两个不可变数据类型)
执行上下文和作用域链
变量或者函数的执行上下文决定了他们可以访问那些数据,每个函数都有自己的执行上下文,当函数被执行的时候, 它的上下文会被推入 执行栈 ,并创建一个作用域链,执行时沿着作用域链查找变量, 函数执行完毕后,执行上下文也会被弹出。
闭包
闭包是指那些引用了另一个函数作用域中的变量的函数,通常在嵌套函数中实现。内部的函数作为参数传递或结果返回, 仍能访问到其所在的外部函数的变量。闭包形成的原因是当一个函数执行完毕时,将会销毁其执行上下文以及附带的活 动对象, 但由于外部函数的活动对象已被添加到内部函数的作用域链中,故无法被销毁,仍然保留在内存中,供内部函 数使用。 闭包的使用场景包括防抖、节流、单次调用函数等。
尾调用优化
尾调用优化是 ES6 规范新增的内存管理优化机制(严格模式下开启),当一个函数的返回值是是它内部返回值的时候, 通过重用执行栈栈帧的 方式优化内存管理(内部函数执行上下文执行完毕后不会直接弹出,而是先判断它的外部栈帧 是否有存在必要)。
构造函数
任何函数只要通过 new
操作符调用就是构造函数(一个函数也可以通过 new.target
来判断自己是否最为构造函数 被调用)。当使用 new
操作符执行构造函数时,js 解释器会在内存中新建一个对象,并将该对象的 __proto__
属性 赋值为构造函数的原型对象 prototype
,然后构造函数内部的 this
被赋值为这个新对象,执行完内部代码后返回 这个对象(如果构造函数直接返回了一个对象,除非手动操作否则原型链会断掉)。
原型和原型链
每个函数(包括 ES6 类)都会创建一个 prototype
属性指向它的原型对象,原型对象的 constructor
属性也会 指向这个函数(或类),当这个函数作为构造函数使用,实例化出一个对象时,这个实例对象的 __proto__
属性也会 指向构它的原型对象。当一个函数的原型对象是另一个构造函数的实例时,就会形成原型链。
为什么 0.1+0.2 不等用 0.3
任何使用了 IEEE754 浮点规范的语言都会存在这个问题,双精度浮点数的可靠位为 15 位,16 位之后的可能是对不上的。 0.1 和 0.2 储存值都比实际值要大一些,所以结果不等于 0.3,比较小数是否相当,应该使用两者的差值与 ES6 新增的 Number.EPSILON
属性比较:
if (0.1 + 0.2 - 0.3 < Number.EPSILON) { console.log(`0.1+0.2=0.3`); }
javascript 如何实现继承
原型链、借用构造函数、组合继承、原型式继承、寄生式继承、寄生式组合继承。详见这里
奇技淫巧
自己实现 call
或者 apply
Function.prototype.myApplay = function (newThis, argArray) { const tempObj = newThis ?? window; const funcSymb = Symbol("tempFunc"); // 当一个函数作为对象的属性调用时,函数内this指向这个对象 // 利用这点来达到绑定传入的newThis的目的 tempObj[funcSymb] = this; tempObj[funcSymb](...argArray); };
自己实现 bind
Function.prototype.myBind = function (newThis) { const self = this; // 利用闭包,绑定this return function () { self.apply(newthis, arguments); }; };
浏览器与 javaScript
HTTP、HTTPS 和 HTTP2
- HTTPS = HTTP + SSL/TLS,(TLS 是 SSL 标准化后的产物)
- SSL 使用非对称加密,对称指的是加密解密使用同一密钥,非对称使用不同密钥
- HTTPS 证书中包含了公钥,发送数据时会使用该公钥加密,接受端使用私钥解密,加大了破解成本,提高安全性
- HTTPS 加密和解密过程会有一定程度的性能损耗
- 目前广泛使用的时 HTTP 协议版本为 1.1
- HTTP2 建立在 HTTPS 协议的基础上,安全
- HTTP2 通过二进制分帧来进行数据传输,高效
- HTTP2 一个域建立一次 TCP 链接,使用多路复用和连接共享,没有 HTTP1 中同个域的并发限制 (得益于分帧机制,帧可以乱序发送,不再依赖多个 TCP 实现并行)
HTTP 缓存机制
浏览器每次发起请求,都会现在浏览器缓存中查找该请求的结果以及缓存标识,且每次拿到结果,都会将该结果 和缓存标识存入浏览器缓存中,而这个缓存过程又分为强制缓存和协商缓存。服务端控制缓存规则的字段包括 Expires
(HTTP1.0 的字段,客户端对比时间存在缺陷,已被后者取代)和 Cache-Control
(优先级更高), Cache-Control<