从上一篇文章JavaScript:prototype属性,我们知道了在Javascript中,原型是用来设置一个构造函数所生成的所有对象共有的属性与函数的方法,它通过函数的prototype
属性开放给我们使用。那么问题来了,给定一个对象o
,如何知道它所对应的原型是什么呢?这里我们要用到对象的内部属性[[Prototype]]
。
我们先来看一个例子:
// 定义一个函数Car
function Car(brand, year) {
// 创建实例变量brand和year
this.brand = brand;
this.year = year;
}
// 创建实例方法getBrand
Car.prototype.getBrand = function() {
return this.brand;
};
// 创建实例方法getYear
Car.prototype.getYear = function() {
return this.year;
}
// 从函数Car创建一个对象
let my_car = new Car("玛莎拉蒂", 2014);
console.log(Object.getPrototypeOf(my_car) === Car.prototype); // true
console.log(my_car.getBrand()); // 玛莎拉蒂
console.log(my_car.getYear()); // 2014
当我们用let car = new Car()
新建一个对象时,我们实际创建了如下图所示的结构:
当我们使用函数来创建一个对象时,所使用的函数又被叫作这个对象的构造函数。在对象被创建后,对象内部会有一个内部属性[[Prototype]]
,指向它的构造函数的prototype
。在这里,两对方括号"[[]]"代表这个属性是内部属性。需要注意的是,内部属性[[Prototype]]
无法直接在代码中使用,要用函数Object.getPrototypeOf
来获取它的值,用函数Object.setPrototypeOf
来改变它的值。
有了这种结构,当我们调用my_car.getBrand()
的时候,Javascript引擎就能够通过内部属性[[Prototype]]
找到相应构造函数的prototype
,并进一步找到函数getBrand
。这样一来,所有通过构造函数Car
创建的对象,都具有了getBrand
和getYear
这两个函数。
所有的对象都有内部属性[[Prototype]]
。
大多数Javascript引擎都会实现一个叫做__proto__
的属性,从而让开发者可以直接通过car.__proto__
来直接读取其内部属性[[Prototype]]
。
遵循ECMAScript标准,
someObject.[[Prototype]]
符号是用于指向someObject
的原型。从 ECMAScript 6 开始,[[Prototype]]
可以通过Object.getPrototypeOf()
和Object.setPrototypeOf()
访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性__proto__
。
但需要注意的是,__proto__
属性并非ECMAScript标准推荐使用的属性,它只在ECMAScript 2015 Language Specification的附录中出现,并且是作为弃用的特性,参考Object.prototype.__proto__ | MDN。
更多关于原型的探讨请参见: