构造函数、this指向和原型链机制 今天在刷力扣[146. LRU 缓存](https://leetcode.cn/problems/lru-cache/)的时候遇到了原型链的写法想想这个写法我正式开发中从来都没有用过到底是个什么玩意遂将各个节点和变量都定义在外面但是代码居然报错啦问了哈吉米大人后才知道代码逻辑没问题但由于力扣每次测试的时候全局定义的变量是不会重置的导致数据残留因此看到了原型链写法了解之后才知道它就是通常说的 class 写法只不过 JavaScript 语言早期的缺陷没有考虑到只能用原型链代替但还好ES6 还是加上了class。class本质上只是“语法糖”它的底层运行机制依然是我们刚刚讲过的“原型链”。在普通的面向对象语言比如 Java/C里有明确的class类概念。但在早期的 JavaScriptES6 之前里是没有真正的class的大家只能用函数来“客串”类。一、new操作符的“四步魔法”在构造函数中this永远指向那个正在被new创造出来的新实例对象本身。1、 凭空创建在内存中创建一个全新的、空的 JavaScript 对象例如let obj {};。2、 基因绑定链接原型将这个新对象的隐藏属性__proto__指向构造函数的prototype共享包。3、 灵魂附体绑定 this将构造函数内部的this强行指向这个刚刚创建的新对象并执行函数体内的代码为新对象添加各种属性。4、 自动交货函数执行完毕后自动返回这个填满属性的新对象除非你的函数手动返回了另一个对象。二、 原型 (prototype) 与 原型链为什么需要原型为了节省内存。如果把所有方法如get、put都写在构造函数内部每次new一个新实例内存中就会复制一份全新的函数代码。核心概念拆解prototype显式原型 / 共享技能包每个函数出生时自带的属性。我们把所有实例共用的方法挂载在这里如LRUCache.prototype.get ...。__proto__隐式原型 / 寻址网线每个实例对象自带的隐藏属性。它指向创造它的那个构造函数的prototype。原型链的工作机制当调用cache.get()时Step 1JS 引擎先在cache这个对象自己的肚子里找get方法。Step 2找不到就顺着cache.__proto__爬到LRUCache.prototype共享包里去找。Step 3如果共享包里还没有继续顺着网线往上爬直到找到顶级对象Object.prototype。如果还是没有就返回undefined或报错。这就是原型链。原型链关系示意图下面通过 Mermaid 流程图直观展示cache实例、LRUCache.prototype和Object.prototype之间的原型链关系顶级原型 (Object.prototype)构造函数原型 (LRUCache.prototype)实例对象 (cache)__proto__ 指向__proto__ 指向__proto__ 指向cache 实例自身属性: capacity, cache, head, tail...LRUCache.prototype共享方法: get(), put(), ...Object.prototype基础方法: toString(), hasOwnProperty(), ...null图例说明cache 实例通过new LRUCache(capacity)创建的具体对象包含实例特有的属性LRUCache.prototype构造函数的原型对象存储所有实例共享的方法Object.prototypeJavaScript 中所有对象的最终原型提供基础方法__proto__链接实例通过__proto__属性指向其构造函数的原型形成原型链当调用cache.get()时JavaScript 引擎会沿着这条链向上查找先在cache自身查找get方法找不到 → 通过cache.__proto__找到LRUCache.prototype在LRUCache.prototype中找到并执行get方法如果还找不到继续向上到Object.prototype最终到null三、this的指向法则黄金定律谁调用了它this就指向谁看点.的左边默认调用独立函数func()没有点调用this默认指向全局对象浏览器环境是window严格模式下是undefined。隐式绑定方法调用obj.func()点左边是objfunc内部的this瞬间指向obj。new 绑定构造调用new Func()this指向全新被构造出来的实例对象。