标签:
Javascript对象具有“自有属性”,也有一些属性是从原型对象继承而来的。为了更好地理解这种继承,必须更深入地了解属性访问的细节。
假设要查询对象o的属性x,如果o中不存在x,那么将会在o的原型对象中查询属性x。如果原型对象中也没有x,但这个原型对象也有原型,那么会继续在这个原型对象的原型上执行查询,直到找到X或者查找到一个原型是null的对象位置。可以看到,对象的原型属性构成了一个“链”,通过这个“链”可以实现属性的继承。
var o = {} //o从object.prototype 继承对象的方法 o.x = 1; //给o定义一个属性x,值为1 var p = inherit(o); // p继承o和object.prototype p.y = 2; //给p定义一个属性y,值为2 var q = inherit(o); // q继承p、o和object.prototype q.z =3; //给q定义一个属性z,值为3 var s = q.toString(); //toString继承自object.prototype q.x + q.y //结果是3,x和y分别继承自o和p
现在假设给对象o的属性x赋值,如果o中已经有属性x(这个属性不是继承来的),那么这个赋值操作只改变这个已有属性x的值。如果o中不存在属性x,那么赋值操作给o添加一个新属性x。如果之前o继承自属性x,那么这个继承的属性就被新创建的同名属性覆盖了。
属性赋值操作首先检查原型链,以此判定是否允许赋值操作。例如,如果o继承自一个只读属性x,那么赋值操作是不允许的。如果允许属性赋值操作,它也总是在原始对象上创建属性或对已有的属性赋值,而不会去修改原型链。
在Javascript中,只有在查询属性时才会体会到继承的存在,而设置属性则和继承无关,这是Javascript的一个重要特性,该特性让程序员有选择地覆盖继承的属性。
var unitcircle = { r : 1}; //一个用来继承的对象 var c = inherit(unitcircle); //c继承属性r c.x = 1; c.y = 1; //c定义两个属性 c.r = 2; //C覆盖继承来的属性 unitcircle.r; //结果是1,原型对象没有修改
属性赋值要么失败,要么创建一个属性,要么在原始对象中设置属性,但有一个例外,如果o继承自属性x,而这个属性是一个具有setter方法的accessor属性,那么这时将调用setter方法而不是给o创建一个属性x。 需要注意的是,setter方法是由对象o调用的,而不是定义这个属性的原型对象调用的。因此如果setter方法定义任意属性,这个操作只是针对o本身,并不会修改原型链。
标签:
原文地址:http://my.oschina.net/u/2352178/blog/476375