原型链
原型链:对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链。
“原型链”的作用:读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype
还是找不到,则返回undefined
。
JavaScript中通过原型链实现了类似面向对象编程语言中的继承,我们在复制一个对象时,只用复制其自身的属性即可,无需将整个原型链进行一次复制,Object.prototype
下的hasOwnProperty
方法可以判断一个属性是否是该对象自身的属性。
实例对象、构造函数、prototype之间的关系可用下图表示:
constructor 属性
constructor属性定义在prototype对象上面,默认指向prototype对象所在的构造函数,可以被所有实例对象继承。
function P() {}
var p = new P();
p.constructor// function P() {}
p.constructor === P.prototype.constructor// true
p.hasOwnProperty('constructor')// false
p
是构造函数P
的实例对象,但是p
自身没有contructor
属性,该属性其实是读取原型链上面的P.prototype.constructor
属性。
instanceof 运算符
instanceof
运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。
instanceof
运算符的左边是实例对象,右边是构造函数。它会检查右边构建函数的原型对象,是否在左边对象的原型链上。
var d = new Date();
d instanceof Date // true
d instanceof Object // true
Object.getPrototypeOf()
Object.getPrototypeOf
方法返回一个对象的原型。这是获取原型对象的标准方法。
// 空对象的原型是Object.prototype
Object.getPrototypeOf({}) === Object.prototype
// true
// 函数的原型是Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype
// true
// f 为 F 的实例对象,则 f 的原型是 F.prototype
var f = new F();
Object.getPrototypeOf(f) === F.prototype
// true
获取原型对象方法的比较
如前所述,__proto__
属性指向当前对象的原型对象,即构造函数的prototype
属性。
var obj = new Object();
obj.__proto__ === Object.prototype
// true
obj.__proto__ === obj.constructor.prototype
// true
上面代码首先新建了一个对象obj
,它的__proto__
属性,指向构造函数(Object
或obj.constructor
)的prototype
属性。所以,两者比较以后,返回true。
因此,获取实例对象obj的原型对象,有三种方法。
obj.__proto__
obj.constructor.prototype
Object.getPrototypeOf(obj)
上面三种方法之中,前两种都不是很可靠。最新的ES6标准规定,__proto__
属性只有浏览器才需要部署,其他环境可以不部署。而obj.constructor.prototype
在手动改变原型对象时,可能会失效。
var P = function () {};
var p = new P();
var C = function () {};
C.prototype = p;
var c = new C();
c.constructor.prototype === p // false
参考链接
http://www.jianshu.com/p/1160d65ce3c3
http://javascript.ruanyifeng.com/oop/prototype.html#toc3