理解prototype、proto和constructor等关系

理解对象和函数的prototype、proto和constructor等关系:

在JavaScript中,函数也是对象。

概述

先给出 构造函数 实例对象 原型对象 三者的关系:

//  概述demo:
function Foo(){};
var f1 = new Foo;

js-proto-1

如图,

[1]构造函数有一个prototype属性,指向实例对象的原型对象。

[2]原型对象有一个constructor属性,指向该原型对象对应的构造函数。

[3]由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数。

[4]实例对象有一个proto属性,指向该实例对象对应的原型对象。

构造函数

用来初始化新创建的对象的函数是构造函数。在上面例子中,Foo()函数是构造函数。

实例对象

可以用一个构造函数,构造多个实例对象。在上面例子中,f1是一个Foo的实例对象。再如:

// 补充demo:
function Foo(){};
var f1 = new Foo;
var f2 = new Foo;
console.log(f1 === f2);//false

原型对象及prototype

[1]构造函数有一个prototype属性,指向实例对象的原型对象。 构造函数Foo()的原型对象是Foo.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

[2]原型对象有一个constructor属性,指向该原型对象对应的构造函数。

function Foo(){};
console.log(Foo.prototype.constructor === Foo);//true

[3]由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数。

function Foo(){};
var f1 = new Foo;
console.log(f1.constructor === Foo);//true

proto

[4]实例对象有一个proto属性,指向该实例对象对应的原型对象。 实例对象f1通过__proto__属性也指向原型对象Foo.prototype。

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto__ === Foo.prototype);//true

视Foo.prototype为实例对象

Foo.prototype是f1的原型对象,同时它也可以是实例对象。实际上,任何对象都可以看做是通过Object()构造函数的new操作实例化的对象。

所以,Foo.prototype作为实例对象时,它的构造函数是Object(),原型对象是Object.prototype。

js-proto-2

相应地,构造函数Object()的prototype属性指向原型对象Object.prototype;

Object.prototype的constructor属性指向构造函数Object()

实例对象Foo.prototype本身具有constructor属性,所以它会覆盖继承自原型对象Object.prototype的constructor属性:

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true

实例对象Foo.prototype的proto属性同样指向原型对象Object.prototype:

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.__proto__ === Object.prototype);//true

视Object.prototype为实例对象

如果Object.prototype作为实例对象的话,其原型对象是什么?结果是null。

js-proto-3

console.log(Object.prototype.__proto__ === null);//true

函数Foo和函数Object也可以被视为实例对象

前面已经介绍过,函数也是对象,只不过是具有特殊功能的对象而已。任何函数都可以看做是通过Function()构造函数的new操作实例化的结果

如果把函数Foo当成实例对象的话,其构造函数是Function(),其原型对象是Function.prototype;类似地,函数Object的构造函数也是Function(),其原型对象是Function.prototype

function Foo(){};
var f1 = new Foo;
console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true

原型对象Function.prototype的constructor属性指向构造函数Function();实例对象Object和Foo本身没有constructor属性,需要继承原型对象Function.prototype的constructor属性:

function Foo(){};
var f1 = new Foo;
console.log(Function.prototype.constructor === Function);//true
console.log(Foo.constructor === Function);//true
console.log(Foo.hasOwnProperty('constructor'));//false
console.log(Object.constructor === Function);//true
console.log(Object.hasOwnProperty('constructor'));//false

js-proto-4

视Function为实例对象

所有的函数都可以看成是构造函数Function()的new操作的实例化对象。 那么,Function可以看成是调用其自身的new操作的实例化的结果

所以,如果Function作为实例对象,其构造函数是Function,其原型对象是Function.prototype

console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.prototype.constructor === Function);//true
console.log(Function.prototype === Function.prototype);//true

视Function.prototype为实例对象

和前面一样,所有的对象都可以看成是Object()构造函数的new操作的实例化结果。

所以,Function.prototype的原型对象是Object.prototype:

console.log(Function.prototype.__proto__ === Object.prototype);//true

刚才介绍过,Object.prototype的原型对象是null:

console.log(Object.prototype.__proto__ === null);//true

总结

对于代码:

function Foo(){};
var f1 = new Foo;

其涉及到的构造函数 实例对象 原型对象 以及它们之间的关系如图所示:

js-proto-4

【1】函数(Function也是函数)是new Function的结果,所以函数可以作为实例对象,其构造函数是Function(),原型对象是Function.prototype

【2】对象(函数也是对象)是new Object的结果,所以对象可以作为实例对象,其构造函数是Object(),原型对象是Object.prototype

【3】Object.prototype的原型对象是null

文章目录
  1. 1. 概述
    1. 1.1. 构造函数
    2. 1.2. 实例对象
    3. 1.3. 原型对象及prototype
    4. 1.4. constructor
    5. 1.5. proto
  2. 2. 视Foo.prototype为实例对象
  3. 3. 视Object.prototype为实例对象
  4. 4. 函数Foo和函数Object也可以被视为实例对象
  5. 5. 视Function为实例对象
  6. 6. 视Function.prototype为实例对象
  7. 7. 总结
|