【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]]内部方法,因此它不是构造函数。