JS中原型与原型链的关系

原型和原型链之间可以说是有着千丝万缕的关系,例如如下代码

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

Person.prototype = {
    sayName: function() {}
}

var p = new Person('Jason')
console.log(p.hasOwnProperty('name'))   //true

上述调用hasOwnProperty()方法,检测其自身是否包含某一属性,而非原型,但是在Person对象中并没有定义hasOwnProperty()方法,但是为什么却能调用hasOwnProperty()方法呢?

JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象。

上述例子中,p也有一个__proto__属性,所以p.__proto__指向Person.prototype。然后,会在Person原型中寻找是否存在hasOwnProperty()方法,结果没有找到,同时,Person.prototype也有__proto__属性,Person.prototype.__proto__指向Object.prototype,那么在Object对象中寻找,结果找到了,就调用该对象中的方法。可见,js是顺着__proto__的指向依次向上寻找对象原型,就好像形成了一条链路,这个就叫做原型链。

不过,要明确的真正重要的一点就是,这个连接存在于实例(p)与构造函数(Person)的原型对象(Person.prototype)之间,而不是存在于实例(p)与构造函数(Person)之间。

那么, Person.__proto__指向什么呢?由于上述的Person可以看做是一个函数的实例,也就是说可以通过new Function()这样的创建方式来创建,所以Person的构造函数就是Function。那么,这个问题就好解决了,Person.__proto__应该指向的是Function.prototype,所以Person.__proto__ === Function.prototype

可以总结为所有函数对象的__proto__都指向Function.prototype,它是一个空函数(Empty function)

所以,js中的包装对象也是如此

Number.__proto__ === Function.prototype  // true
Number.constructor == Function //true

Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true

String.__proto__ === Function.prototype  // true
String.constructor == Function //true

// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Object.__proto__ === Function.prototype  // true
Object.constructor == Function // true

// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Function.__proto__ === Function.prototype // true
Function.constructor == Function //true

Array.__proto__ === Function.prototype   // true
Array.constructor == Function //true

RegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //true

Error.__proto__ === Function.prototype   // true
Error.constructor == Function //true

Date.__proto__ === Function.prototype    // true
Date.constructor == Function //true

总结如下:所有对象的 __proto__ 都指向其构造器的 prototype

有一个比较特殊的属性Function,可以看到typeof Function.prototype === "function",除了这个之外,所有的包装对象的原型以及自定对象的原型为object

typeof Person.prototype;  //object
typeof Number.prototype;  //object
typeof Function.prototype;   //function

那么下面这段代码该输出什么呢?

Function.prototype.__proto__ === Object.prototype

其运行结果为true,看起来比较费解。因为Function.prototype是一个函数对象,所以Function.prototype.__proto__指向其自己,没有意义,所以就让其指向Object.prototype,正好通过Object的原型,可以让其最终指向顶部null,从而保证原型链能够正常结束。

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

1条评论

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注