【JavaScript】深度剖析prototype与__proto__到底是什么以及他们的关系
一个对象的 __proto__ 指向的是这个对象的构造函数的 prototype。
prototype 是什么
prototype 是函数的属性,是一个继承自 Object 的对象,默认的 prototype 只有一个属性,其中包含 constructor,指向当前函数自身。
Ctor.prototype = Object.create(Object.prototype, {
constructor: { value: Ctor },
});
一个 Function 对象在使用 new 运算符来作为构造函数时,会将它的 prototype 属性作为新对象的原型。
function Ctor() {}
const inst = new Ctor();
Ctor.prototype === Object.getPrototypeOf(inst); // true
Ctor.prototype === inst.__proto__; // true
__proto__ 是什么
__proto__ 是对象的属性,是对象的原型对象,如果在对象上没有找到某个属性则会沿着对象的原型链查询,所有的对象都继承自 Object。
普通对象的 __proto__ 属性是对象,函数的 __proto__ 是一个内置函数。
创建一个对象时会给这个对象一个 __proto__ 属性,指向其构造函数的 prototype 属性。
function Ctor() {}
const inst = new Ctor();
inst.__proto__ === Ctor.prototype; // true
inst.__proto__.constructor === Ctor; // true
inst.constructor === Ctor; // true
inst.hasOwnProperty("constructor"); // false constructor 是 inst.__proto__ 上的属性
未用 new 操作符创建的对象默认构造函数为 Object:
const obj = {};
obj.constructor === Object; // true
函数的独特之处
JavaScript 中万物皆为对象,函数也是一种特殊的对象,所有的函数都继承自 Function。
function Ctor() {}
Ctor.__proto__ === Function.prototype; // true
关于 Function:
Function.constructor指向Function自身。Function.prototype是一个函数。
Function.constructor === Function; // true
Function.prototype; // ƒ () { [native code] }
Function.prototype.__proto__ === Object.prototype; // true
需要注意的是,函数继承自 Function,但是用函数作为构造函数创建出的实例对象是继承自 Object 的。
function Ctor() {}
const inst = new Ctor();
Object.prototype.tag = "obj";
console.log(Function.tag); // obj
console.log(Ctor.tag); // obj
console.log(inst.tag); // obj
Function.prototype.tag = "func";
console.log(Function.tag); // func
console.log(Ctor.tag); // func
console.log(inst.tag); // obj
Ctor.prototype.tag = "ctor";
console.log(Function.tag); // func
console.log(Ctor.tag); // func
console.log(inst.tag); // ctor
Q&A
Ctor.prototype 是什么
函数的 prototype 是一个继承自 Object 的对象,默认的 prototype 只有一个属性,其中包含 constructor,指向当前函数自身,可以这样定义:
Ctor.prototype = Object.create(Object.prototype, {
constructor: { value: Ctor },
});
Ctor.__proto__ 是什么
js 中的函数也是一种对象,函数对象的构造函数是 Function,对象的原型指向其构造函数的 prototype,因此函数的 __proto__ 属性指向 Function.prototype。
注意 Function.prototype 是一个内置函数。
function Ctor() {}
Ctor.__proto__ === Function.prototype; // true
Function.prototype; // ƒ () { [native code] }
Ctor.prototype.__proto__ 指向什么
所有对象的默认构造函数都是 Object,Ctor.prototype 的原型就是其构造函数的 prototype 即 Object.prototype。
function Ctor() {}
Ctor.prototype.__proto__ === Object.prototype;
为什么 Function.prototype 是函数
之前说过函数的 prototype 是对象,但是 Function.prototype 却是一个函数,在 ECMAScript® 2015 Language Specification中描述了这样做的原因:
NOTEThe Function prototype object is specified to be a function object to ensure compatibility with ECMAScript code that was created prior to the ECMAScript 2015 specification。
注:Function 原型对象被指定为函数对象,以确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码兼容。
Function 原型对象本身就是一个内置函数对象。当被调用时,它接受任何参数并返回 undefined。它没有[[Construct]]内部方法,因此它不是构造函数。