先来看一下这两个属性在网页的控制台显示出的内容:
其中,prototype表示的是原型,而相当于我们之后写的__proto__(这里一共是四个下划线),表示的是原型链。
原型:用prototype表示,表示 类与类之间的父子关系。一个函数或者类,都含有一个prototype属性,这个属性是一个指针,会指向一个原型对象,比如上面的图片,Point类指向了Object对象。事实上,这个属性也可以用来区分是否是对象还是类(函数)。
原型链:用__proto__属性表示,表示 是某类的对象。原型链是每个对象或者类都拥有的一个属性,这个属性也是一个指针,它指向一个从属于它的原型对象, 比如上面的图片,指向的就是function对象。对象的__proto__和它从属类的__proto__指向同一空间。
对上述的概念进行一个探究。
执行下述代码:
// 生成了一个Point类
function Point (row, col) {
// set方法
this.setRow = function (row) {
this.row = row ? row : 1;
}
this.setCol = function (col) {
this.col = col ? col : 1;
}
// get方法
this.getRow = function () {
return this.row;
}
this.getCol = function () {
return this.col;
}
this.toString = function () {
return '(' + row + ", " + col + ')';
}
// 执行set方法
this.setRow(row);
this.setCol(col);
}
// 对Point类进行输出
console.log("Point:", Point);
// 分别生成三个Point对象,并分别输出
var point1 = new Point(4, 6);
var point2 = new Point(5);
var point3 = new Point();
console.log(point1);
console.log(point2);
console.log(point3);
其执行结果如下:
点开上述的箭头,可以发现,prototype属性是区别于对象和类的一个属性。然而,类和对象均有__proto__属性,类的__proto__指向的是一个function对象,对象的__proto__指向的是一个object对象。那么,这里的object和function到底是什么东西,object和function之间到底是个什么关系呢?继续探究:
// 单独对Function和Object进行输出
console.log("Function:", Function);
console.log("Object:", Object);
执行结果:
可以发现,红框圈起来的,有相同的部分,但是,Object也有许多Function没有的属性,而且,Function这个类的属性Object全部具有。那么Object和Function到底是什么关系?继续探究;
// 输出Object和Function的从属关系
console.log("Object instanceof Function:", Object instanceof Function);
console.log("Object instanceof Object:", Object instanceof Object);
console.log("Function instanceof Object:", Function instanceof Object);
结果如下:
这个结果还是搞不清楚,这两只之间的关系;
那就继续验证:
// 比较彼此和原型链和原型对象之间的关系
console.log("Object.__proto__ === Function.prototype:", Object.__proto__ === Function.prototype);
console.log("Object.prototype.__proto__ === Object.prototype:", Object.prototype.__proto__ === Object.prototype);
console.log("Object.prototype.__proto__:", Object.prototype.__proto__);
结果如下:
这时,可以清楚的发现,Function的原型所指向的对象空间就是Object的原型链所指向的空间,然而Object的原型所指向的原型对象的原型链所指向的空间不是Object的原型链所指向的空间,Object的原型链所指向的空间是null,证明Object的原型链是“链”的末尾。
再验证一下Function类和普通的对象之间的关系:
// Function类的原型所指向的空间和对象的原型链所指向的空间是否相同?
console.log("Function.prototype === Point.__proto__:", Function.prototype === Point.__proto__);
// Point类和Function类的从属关系
console.log("Point instanceof Function:", Point instanceof Function);
// Function类的原型所指向的空间和原型链所指向的空间是否相同?
console.log("Function.prototype === Function.__proto__:", Function.prototype === Function.__proto__);
// Function是否从属于自己
console.log("Function instanceof Function:", Function instanceof Function);
执行结果:
由此,可以画出一张图进行说明:
Point是一个类,这个类有三个对象,三个point对象的原型链都指向了Point类的原型所指向的空间。而Point类的原型链指向了Function类的原型链所指向的空间。Function类的原型链所指向的空间是所有类共同指向的空间,而这个空间最终指向类Object类的原型所指向的空间。Object类的原型所指向的空间是“链”的结尾。
也就是说,从原型链来说,所有类和对象的原型链均指向了Function类的原型链所指向的空间,但是所有类的原型和这个原型链最终都指向了Object的原型(prototype)所指向的空间。这也就不难理解,为什么
console.log(“Object instanceof Function:”, Object instanceof Function);
console.log(“Object instanceof Object:”, Object instanceof Object);
console.log(“Function instanceof Object:”, Function instanceof Object);
结果均为 true !!!