这里,我们列出原型的几个概念,如下:
- prototype属性
- [[prototype]]
__proto__
<!--more-->
prototype属性
只要创建了一个函数,就会为该函数创建一个prototype
属性,指向该函数的原型对象。实例对象是不会拥有该属性的。
默认情况下,该原型对象
也会获得一个constructor
属性,该属性包含一个指针,指向prototype
属性所在的函数。
function Person() {}// 只是一个函数而已
Person.prototype.constructor === Person
[[prototype]]和__proto__
javascript中,不可以访问的内部属性都是用[[propertyName]]
这种形式来表示的,比如还有枚举属性[[Enumberable]]。
[[prototype]]
属性只能是对象可以拥有的属性。比如实例化的对象以及原型对象
,而不是构造函数。这个属性指向拥有其属性的对象的构造函数的原型对象。注意,此处的构造函数
指的是使用new
方式的构造函数。并不因为更改了原型对象上的constructor
属性而改变。
比如:
function Person() {}
Person.prototype.constructor = {}; // 此处修改了Person原型的构造函数指向
let p = new Person();
p.__proto__ === Person.prototype; // true
__proto__
是个啥呢,就是对[[propertyName]]
的实现。也就是说,你可以在支持该实现的浏览器下(FF,chrome,safari),去访问对象的构造函数的原型对象。比如:
var Person = function(name) {
this.name = name;
};
var p1 = new Person();
p1.__proto__=== Person.prototype; // true
Person.prototype = {};
var p2 = new Person();
p2.__proto__ === Object.prototype; // false
当然,__proto__
只是浏览器的私有实现,目前ECMAScript标准实现方法是Object.getPrototypeOf(object)
。
var Person = function(name) {
this.name = name;
};
var p1 = new Person();
Object.getPrototypeOf(p1) === Person.prototype; // true
Person.prototype = {};
var p2 = new Person();
Object.getPrototypeOf(p2) === Object.prototype; // false
另外一种判断实例对象和其原型对象存在指向关系(由实例的[[prototype]]指向其构造函数的原型对象)的方法是:isPrototypeOf
。比如:
Person.prototype.isPrototypeOf(p1); // true
由于函数和原型对象
也是一个对象,所以,它自然而然也拥有[[prototype]]
属性。
弄清楚了这些概念,原型链,继承等存在的一些问题,都不是问题了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。