2

这里,我们列出原型的几个概念,如下:

  • 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]]属性。

弄清楚了这些概念,原型链,继承等存在的一些问题,都不是问题了。

clipboard.png


52lidan
2.8k 声望85 粉丝

写代码要有追求