ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaScript 原型链:prototype、proto、new 与 instanceof

JavaScript 原型链:prototype、proto、new 与 instanceof JavaScript 原型链最核心的三个角色是构造函数 实例对象 原型对象例如function Person(name) { this.name name } const p new Person(Tom)这里Person → 构造函数 p → 实例对象 Person.prototype → 一个普通对象会成为 p 的原型理解这三个东西原型链基本就通了。一、什么是对象的原型JavaScript 中一个对象通常会关联另一个对象。这个被关联的对象就叫这个对象的原型。例如const p new Person()p的原型就是Person.prototype可以验证Object.getPrototypeOf(p) Person.prototype // true也就是p ↓ 原型 Person.prototype如果p自己找不到某个属性就会去它的原型Person.prototype上继续查找。二、Person.prototype 到底是什么这是最容易混淆的地方。function Person() {}Person是一个函数对象它身上有一个名为prototype的属性。所以Person.prototype本质只是读取 Person 身上名叫 prototype 的属性。而这个属性保存的值恰好是一个普通对象typeof Person.prototype // object可以理解成Person ↓ .prototype 属性 Person.prototype 这个对象这个对象的作用是以后通过new Person()创建出来的实例会把它作为自己的原型。所以const p new Person() Object.getPrototypeOf(p) Person.prototype // true三、Person.prototype 是 Person 自己的原型吗不是。这是非常关键的区别。Person.prototype只是Person身上的一个普通属性。而要获取Person 这个函数对象自己的原型应该写Object.getPrototypeOf(Person)结果通常是Function.prototype所以Object.getPrototypeOf(Person) Function.prototype // true两条关系完全不同Person ↓ .prototype 属性 Person.prototype和Person ↓ 自己的原型 Function.prototype所以一定要记住.prototype不等于“获取对象的原型”。四、是不是所有对象都有 prototype不是。普通对象通常没有const user {} user.prototype // undefined实例p也一样p.prototype // undefined但是p明明有自己的原型。想获取它应该写Object.getPrototypeOf(p)结果Person.prototype所以.prototype → 普通属性名 对象的原型 → 对象内部真正关联的另一个对象这两个概念必须分开。五、Person.prototype 自己也有原型吗有。因为Person.prototype本身就是一个普通对象。普通对象也可以有自己的原型。所以Object.getPrototypeOf(Person.prototype)通常得到Object.prototype也就是Object.getPrototypeOf(Person.prototype) Object.prototype // true所以关系是p ↓ Person.prototype ↓ Object.prototype ↓ null六、为什么不能写 Person.prototype.prototype因为Person.prototype.prototype并不是获取 Person.prototype 的原型。它真正的意思是在 Person.prototype 这个对象上找一个名字叫prototype的属性。而它默认没有这个属性所以Person.prototype.prototype // undefined如果想获取Person.prototype自己的原型应该写Object.getPrototypeOf(Person.prototype) // Object.prototype所以Person.prototype.prototype → 找 prototype 属性 Object.getPrototypeOf(Person.prototype) → 获取真正的原型七、Object.getPrototypeOf() 是什么Object.getPrototypeOf()用来获取一个对象真正关联的原型。例如Object.getPrototypeOf(p) // Person.prototype也就是在问p 的原型是谁答案Person.prototype同理Object.getPrototypeOf(Person) // Function.prototype表示Person 自己的原型是谁而Object.getPrototypeOf(Person.prototype) // Object.prototype表示Person.prototype 这个对象自己的原型是谁这三个非常重要Object.getPrototypeOf(p) Person.prototype // true Object.getPrototypeOf(Person) Function.prototype // true Object.getPrototypeOf(Person.prototype) Object.prototype // true八、proto是什么以前经常使用p.__proto__它也可以访问对象的原型。所以p.__proto__ Person.prototype // true通常p.__proto__ Object.getPrototypeOf(p) // true不过__proto__属于历史遗留方式。现在更推荐Object.getPrototypeOf(p)可以简单理解__proto__ → 旧式访问对象原型 Object.getPrototypeOf() → 推荐方式九、constructor 是什么Person.prototype是一个对象。它默认有一个constructor属性指回对应的构造函数Person.prototype.constructor Person // true所以Person │ │ .prototype ↓ Person.prototype │ │ .constructor ↓ Person可以记成prototype 构造函数 → 原型对象 constructor 原型对象 → 构造函数十、new 做了什么例如const p new Person()new最关键的一步就是把 Person.prototype 这个对象设置成 p 的原型。所以Object.getPrototypeOf(p) Person.prototype // true也就是Person ↓ .prototype Person.prototype ↑ │ p 的原型 p因此可以说p 的原型就是 Person 身上 prototype 属性保存的那个对象。十一、什么是原型链p的原型是Person.prototype而Person.prototype自己的原型又是Object.prototypeObject.prototype的原型最终是null于是形成p ↓ Person.prototype ↓ Object.prototype ↓ null这条链就是原型链 Prototype Chain当对象自身找不到属性时就会沿着这条链向上查找。例如p.toString()查找过程可能是p ↓ 没有 Person.prototype ↓ 没有 Object.prototype ↓ 找到 toString所以对象能使用某个方法不代表这个方法一定属于对象自己也可能来自原型链。十二、instanceof 为什么和原型链有关例如p instanceof Person // trueinstanceof真正判断的是Person.prototype是否存在于p的原型链中。因为p ↓ Person.prototype ↓ Object.prototype ↓ null其中确实存在Person.prototype所以返回true最终关系图最重要的关系可以画成.prototype 属性 Person ─────────────────────────→ Person.prototype │ ↑ │ │ │ 自己的原型 │ p 的原型 ↓ │ Function.prototype p p ↓ Person.prototype ↓ Object.prototype ↓ null同时Person.prototype ↓ .constructor Person对应代码Object.getPrototypeOf(p) Person.prototype // true Object.getPrototypeOf(Person) Function.prototype // true Object.getPrototypeOf(Person.prototype) Object.prototype // true Person.prototype.constructor Person // true p instanceof Person // true总结概念含义原型一个对象真正关联的上层对象原型对象被其他对象当作原型使用的对象prototype函数身上的普通属性保存一个对象Person.prototype将来提供给 Person 实例作为原型的对象Object.getPrototypeOf(obj)获取 obj 真正的原型__proto__访问对象原型的旧式方式constructor原型对象默认指回构造函数的属性原型链对象沿着原型不断向上连接形成的链最需要记住的是const p new Person() Object.getPrototypeOf(p) Person.prototype意思是Person.prototype是 Person 身上一个普通属性保存的对象new Person()创建出来的实例p会把这个对象作为自己的原型。而Object.getPrototypeOf(Person)才是在获取Person 自己的原型。最后把整套关系压缩成一句话.prototype是函数身上的属性对象真正的原型要用Object.getPrototypeOf()获取new会把构造函数的prototype对象设置成实例的原型多个原型继续向上连接就形成了原型链。
返回列表