Javascript对象具有“自有属性”(own property),也有一些属性是从原型对象继承而来的。为了更好地理解对象自有属性和继承属性下面的示例深入解释了属性的访问和设置细节。
function Obj () {
this.z = 3;//自有属性
}
//对象会继承原型里的属性
Obj.prototype.x = 1;
Obj.prototype.y = 2;
var o = new Obj();
console.log(o); //o的打印结果如下图,可以看到其自有属性和继承自原型的属性
假设要查询对象o的属性y, 如果o自有属性中不存在y, 那么会继续在o的原型对象中查找属性y。如果原型对象中也没有y,但这个原型对象也有原型,那么继续在这个原型对象的原型上执行查询,直到没找到y或者查找到一个原型是null的对象为止。 对象的原型属性构成了一个“链”。 通过这个“链”可以实现属性的继承。
现在假设给对象o的属性x赋值,如果o中已经有属性x(自有属性,不是继承来的)那么这个赋值操作只改变这个已有属性x的值。如果o中不存在属性x, 那么赋值操作给o添加一个新属性x。 如果之前o继承了自己的原型对象的x属性,那么这个继承的属性就被新创建的同名属性屏蔽了。
o.x = 5;
console.log(o);
console.log(o.x);// 5
从打印结果可以看到对象创建了一个自有属性x,屏蔽了之前继承来的x值,这个操作只影响o这个单一对象,不会影响对象的原型里的x属性,既不会影响其他继承该原型的对象。
var b = new Obj();
console.log(b);
console.log(b.x);//1
我们再把对象o的x属性delete掉,然后再访问属性“x”
delete o.x;//true
o.x; // 1
发现访问o.x
时 x
再次指向了原型对象中的 x
属性。
实际上自有属性和继承属性与静态语言的实例属性和类属性很像,因此在编写程序的时候最好不要把实例属性和类属性使用相同的名字,因为相同名字的实例属性会屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称访问到的将是类属性。
在给对象的属性赋值时,是在原始对象上创建属性或者对已有属性赋值,而不会去修改原型链。在Javascript中,只有查询属性时才会体会到继承的存在,而设置属性则和继承无关,该特性可以让我们可以有选择地覆盖继承的属性。