jtwang7 / JavaScript-Note

JavaScript学习笔记
10 stars 2 forks source link

JS 基础篇 - prototype与__proto__的关系与区别 #51

Open jtwang7 opened 3 years ago

jtwang7 commented 3 years ago

参考文章:

前言 Object & Function

JS 中引用类型有很多: Object, Function, Array, Date …; 其中 Object, Function 是能被 typeof 识别的, 其余的本质上都是 Object 的衍生对象; Function 在 JS 中被单独视为一类, 是因为它在 JS 中是所谓的一等公民, JS 中没有类的概念, 其是通过函数来模拟类的; 尽管 Function 被单独视为一类,但从形式上看,它还是一个 Object 对象,那么我们如何区分 Function 和 Object 呢?答案就是 prototype

prototype & [[Prototype]]

prototype 是用来区分 Function 和 Object 的关键: 函数创建时, JS 会为函数自动添加 prototype 属性, 其值为一个带有 constructor 属性(指向对应的构造函数)的对象,这个对象就是我们所说的原型对象,除了 constructor 属性外,我们还可以在上面添加一些公用的属性和方法;

Function.prototype = {
  constructor: Function,
  // ...
}

而每个对象则都有一个内部属性[[Prototype]], 其用于存放该对象对应的原型对象。 但是对象的内部属性[[Prototype]]是无法被直接访问和获取的,需要通过 __proto__ , Object.getPrototypeOf / Object.setPrototypeOf访问.

你可以理解为,[[Prototype]] 存放了对原型对象的引用,真正的原型对象是由 Function.prototype 创建和维护的。

prototype 与 proto 的联系

  1. __proto__ 存在于所有对象上, prototype 只存在于函数上;
  2. 每个对象都对应一个原型对象, 并从原型对象继承属性和方法, 该对应关系由 __proto__ 实现(访问对象内部属性[[Prototype]]);
  3. prototype 用于存储共享的属性和方法, 其作用主要体现在 new 创建对象时, 为 __proto__ 构建一个对应的原型对象(设置实例对象的内部属性[[Prototype]]);
  4. __proto__ 不是 ECMAScript 语法规范的标准, 是浏览器厂商实现的一种访问和修改对象内部属性 [[Prototype]] 的访问器属性(getter/setter), 现常用 ECMAScript 定义的 Object.getPrototypeOfObject.setPrototypeOf 代替;
  5. prototype 是 ECMAScript 语法规范的标准;

总结来说:[[Prototype]] 是对象内维护其对应原型对象的属性,但它不可直接被外界访问和修改;__proto__ 是浏览器厂商实现的访问和修改对象内部属性 [[Prototype]] 的访问器属性(getter/setter),不规范,现多用ECMAScript 定义的 Object.getPrototypeOfObject.setPrototypeOf 代替;而 prototype 则是原型对象真正创建和存储的地方,在这里可以定义一些公用的属性和方法。