JavaScript原型与原型链的个人理解

JavaScript原型与原型链的问题也是最近发现的知识盲区。大概意思就是JavaScript虽然有对象,但是没有类似于C++以及Java的类,JavaScript的对象实际是从各种各样的原型继承而来的,这个就是基本概念。

首先提出两个概念:

  • 每个函数都有一个prototype属性,这个属性指向函数的原型对象。
  • 每个对象(除null外)都有一个__proto__属性,这个属性会指向该对象的原型。
  • 所有的对象都由函数创建

需要注意的是,JavaScript中,函数也属于对象,所以函数除了prototype属性,也会具有__proto__属性。

prototype属性

prototype属性只出现在函数中,无论该函数是构造函数还是普通函数,都会有prototype属性,并且指向函数的原型对象。

请看下面代码:

function clicc(){
    var i = 11+11;
    console.log(i);
}
console.dir(clicc);

可以在chrome控制台中得到如下内容

用一张图来抛出结论

再举一个例子,构造函数如下:

function Person(name) {
    this.name = name;
}

仍然可以通过console.dir(Person)来获得如下内容

对应的Person函数的结论也如下

__proto__属性

__proto__属性我也在前面说过,仅出现在对象中,指向该对象的原型,上面我们定义了构造函数Person,可以new一个Person对象。

function Person(name) {
    this.name = name;
}
var person = new Person('小明');

通过上述代码我们创建了person这个对象,下面来进行一个验证:

console.log(person.__proto__ === Person.prototype);

以上代码会返回true,也就是说对象person的__proto__属性指向的东西跟构造函数Person的prototype属性指向的东西完全相同。通过结论可以得出关系图如下:

constructor属性

constructor是实例原型的一个属性,该属性指向关联的构造函数。

function Person(name) {
    this.name = name;
}
var person = new Person('小明');
console.log(Person===Person.prototype.constructor);

上述代码返回true结果,可以进一步优化关系图:

Object

我们都清楚JS中可以通过new Object()来新建一个对象,先运行下面代码:

var obj = new Object();

通过Object函数创建对象之后,运行下面的对比代码:

console.log(Person.prototype.__proto__ === obj.__proto__)

上述代码将返回一个true结果,也就是说Person.prototype这个东西的__proto__属性指向了Object.prototype,由此结论可以得出以下关系图

当然,上述代码其实只是验证了Person.prototype.__proto__与obj.__proto__的关系,如果你对于Object与Object.prototype之间的关系或者其他的关系存疑,也可以通过类似的方法进行验证。

为什么Person.prototype的__proto__属性会指向Object.prototype呢?其实这涉及的一个概念:JavaScript中万物皆对象。虽然我没有对这句话的真伪进行过深入的思考,但是目前来看,JS中很多内容都是继承自Object.prototype的。

原型链

那么所有函数(包括构造函数和普通函数在内的所有函数)的__proto__属性指向谁呢?

实际上,JS中任何函数的prototype属性或者对象的__proto__属性,沿着一层又一层的__proto__指向,最终都会回到Object.prototype这个实例原型上。这些向上溯源的__proto__属性所连成链状结构就是原型链。

发表评论

电子邮件地址不会被公开。 必填项已用*标注