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
,从而保证原型链能够正常结束。
- 本博客所有文章除特别声明外,均可转载和分享,转载请注明出处!
- 本文地址:https://www.leevii.com/?p=955
1条评论