JavaScript:属性赋值和原型链

本文要研究一下:一个对象的原型链是如何影响该对象自身的属性赋值操作的.本文更详细的阐述了一下上篇文章“[译]JavaScript中的属性:定义和赋值的区别”中提到的一个知识点.

创新互联主营安泽网站建设的网络公司,主营网站建设方案,成都APP应用开发,安泽h5微信平台小程序开发搭建,安泽网站营销推广欢迎安泽等地区企业咨询

原型链

每个对象都有一个包含了一个或者多个对象的原型链,该对象正是这个原型链的起始对象.原型链上的所有对象的所有属性都可以被该对象访问到.例如:

 
 
 
  1. > var proto = { foo: 1 };  
  2. > var obj = { __proto__: proto, bar: 2 };  
  3. > obj.foo  
  4. 1  
  5. > obj.bar  

我们用到了特殊属性 __proto__  来创建原型链(该属性还没有被所有浏览器广泛支持).对象obj的原型链包含了三个对象:起始处是obj,紧跟着proto,***是Object.prototype. Object.prototype是Object构造函数的原型对象,绝大部分原型链中都包含了它(大部分,但不是全部):

 
 
 
  1. > Object.prototype.isPrototypeOf({})  
  2. true 
  3. > Object.prototype.isPrototypeOf([])  
  4. true 
  5. > Object.prototype.isPrototypeOf(new Date())  
  6. true 

而且它是原型链的截止对象:

 
 
 
  1. > Object.getPrototypeOf(Object.prototype)  
  2. null 

普通对象的很多标准方法都是从Object.prototype上继承下来的,比如toString()和hasOwnProperty().

为属性赋值

如果你给一个属性赋值,你通常只能修改原型链上的起始对象(也就是对象自身):如果自身属性已经存在了,则改变这个属性的值,否则,创建这个新的自身属性:

 
 
 
  1. > obj.foo = 3;  
  2. > obj.foo  
  3. 3  
  4. > obj.hasOwnProperty("foo")  
  5. true 
  6. > proto.foo  

这样设计的目的是:一个原型可以为其所有的实例引入了一个公用的初始值(被继承的属性的值).如果给其中一个实例的同名属性执行赋值操作可以改变原型上的那个公用的属性值的话,那么所有实例的初始值都会被改变.为了防止这种情况发生,同时还允许你修改某单个实例的初始值,属性的赋值操作被设计为:仅允许你改变一个已存在的自身属性的值.如果还没有这个自身属性,则会自动创建,再赋值.

访问器和原型链

一个存在于原型链上的访问器属性[3]可以阻止"在该原型链的起始对象上创建同名的自身属性".假如对象obj继承了一个拥有getter和setter的对象:

 
 
 
  1. var obj = {  
  2.     __proto__: {  
  3.         get foo() {  
  4.             return 1;  
  5.         },  
  6.         set foo(x) {  
  7.             console.log("Setter called: "+x);  
  8.         }  
  9.     }  
  10. };  

给对象obj的属性foo赋值的话,会调用到其原型上的setter访问器,而不会给obj创建一个自身属性foo,同理,读取obj的foo属性的话,也会调用到其原型上的getter访问器:

 
 
 
  1. > obj.foo = 2;  
  2. Setter called: 2  
  3. > obj.foo  

如果你想禁止该属性的赋值操作的话(也就是只读),可以不提供setter:

 
 
 
  1. var obj = {  
  2.     __proto__: {  
  3.         get foo() {  
  4.             return 1;  
  5.         }  
  6.     }  
  7. };  
  8.  

这样的赋值操作,在非严格模式下会静默失败,在严格模式下,会抛出异常:

 
 
 
  1. > (function () { "use strict"; obj.foo = 2; }());  
  2. TypeError: Cannot set property foo of obj which has only a getter 

原型链上的只读属性

如果原型链上的起始对象继承了一个只读属性,则你无法通过赋值操作改变这个属性的值.例如,下面的代码:

 
 
 
  1. var proto = Object.defineProperty({},  
  2.     "foo",  
  3.     {  
  4.         value: 1,  
  5.         writable: false 
  6.     });  
  7. var obj = { __proto__: proto }; 

你无法给obj.foo赋值:

 
 
 
  1. > (function () { "use strict"; obj.foo = 2; }());  
  2. TypeError: obj.foo is read-only 

这正好和只有getter的访问器属性的表现相一致.这一次,原型上的属性同样可以作为一个共享的初始值,不同的是,我们要防止单个实例更改自己的初始值.如果你想要给obj创建一个自身属性foo,则你可以使用Object.defineProperty()和Object.defineProperties()来完成.

英文原文:http://www.2ality.com/2012/11/property-assignment-prototype-chain.html

原文链接:http://www.cnblogs.com/ziyunfei/archive/2012/11/08/2759680.html

分享文章:JavaScript:属性赋值和原型链
网站URL:http://www.shufengxianlan.com/qtweb/news22/7672.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联