详解prototype、proto和constructor的关系
代码示例
function Foo() {};
var f1 = new Foo;
构造函数
用来初始化新创建的对象的函数是构造函数。上例中Foo()就是构造函数
实例对象
通过构造函数的new操作符创建的对象是实例对象。一个构造函数可以构造多个实例对象
function Foo() {};
var f1 = new Foo;
var f2 = new Foo;
console.log(f1 === f2); //false
原型对象及prototype
构造函数有一个prototype属性,指向实例对象的原型对象。构造函数实例化的多个对象具有相同的原型对象,可用原型对象来实现继承
function Foo() {};
Foo.prototype.a = 1;
var f1 = new Foo;
var f2 = new Foo;
console.log(Foo.prototype.a); //1
console.log(f1.a); //1
console.log(f2.a); //1
constructor
原型对象有一个constructor属性,指向该原型对象对应的构造函数
function Foo() {};
console.log(Foo.prototype.constructor === Foo) //true
由于实例对象可用继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数
function Foo() {};
var f1 = new Foo;
console.log(f1.constructor == Foo); //true
proto
实例对象有一个proto属性,指向该实例对象对应的原型对象
function Foo() {};
var f1 = new Foo;
console.log(f1.__proto__ === Foo.prototype); // true
总结
- 函数是new Function的结果,所以函数可以作为实例对象,其构造函数是Function(),原型对象是Function.prototype
- 对象是new Object的结果,所以对象可以作为实例对象,其构造函数是Object(),原型对象是Object.prototype
- Object.prototype的原型对象是null
- __proto__是实例对象的属性,指向其构造函数的prototype属性,即指向原型对象
- 原型对象有一个constructor属性,指向该原型对象对应的构造函数
Tips
typeof null === "Object"
原因是在js中,不同对象在底层都是以二进制标识,二进制前三位如果都是0的话就会被判定为Object类型,null的二进制都是0,所以返回Object