开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1203|回复: 1
收起左侧

[js/PHP求助] JavaScript:属性赋值和原型链

[复制链接]

发表于 2013-2-4 13:54:50 | 显示全部楼层 |阅读模式   广东省汕尾市
本文要研究一下:一个对象的原型链是如何影响该对象自身的属性赋值操作的.本文更详细的阐述了一下上篇文章“[译]JavaScript中的属性:定义和赋值的区别”中提到的一个知识点.
原型链
每个对象都有一个包含了一个或者多个对象的原型链,该对象正是这个原型链的起始对象.原型链上的所有对象的所有属性都可以被该对象访问到.例如:

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

    > Object.prototype.isPrototypeOf({})  
  • true
    > Object.prototype.isPrototypeOf([])  
  • true
    > Object.prototype.isPrototypeOf(new Date())  
  • true
而且它是原型链的截止对象:

    > Object.getPrototypeOf(Object.prototype)  
  • null
普通对象的很多标准方法都是从Object.prototype上继承下来的,比如toString()和hasOwnProperty().
为属性赋值
如果你给一个属性赋值,你通常只能修改原型链上的起始对象(也就是对象自身):如果自身属性已经存在了,则改变这个属性的值,否则,创建这个新的自身属性:

    > obj.foo = 3;  
  • > obj.foo  
    3  
  • > obj.hasOwnProperty("foo")  
    true
  • > proto.foo  
  • 1
这样设计的目的是:一个原型可以为其所有的实例引入了一个公用的初始值(被继承的属性的值).如果给其中一个实例的同名属性执行赋值操作可以改变原型上的那个公用的属性值的话,那么所有实例的初始值都会被改变.为了防止这种情况发生,同时还允许你修改某单个实例的初始值,属性的赋值操作被设计为:仅允许你改变一个已存在的自身属性的值.如果还没有这个自身属性,则会自动创建,再赋值.
访问器和原型链
一个存在于原型链上的访问器属性[3]可以阻止"在该原型链的起始对象上创建同名的自身属性".假如对象obj继承了一个拥有getter和setter的对象:

    var obj = {  
  •     __proto__: {  
            get foo() {  
  •             return 1;  
            },  
  •         set foo(x) {  
                console.log("Setter called: "+x);  
  •         }  
        }  
  • };  
给对象obj的属性foo赋值的话,会调用到其原型上的setter访问器,而不会给obj创建一个自身属性foo,同理,读取obj的foo属性的话,也会调用到其原型上的getter访问器:

    > obj.foo = 2;  
  • Setter called: 2  
    > obj.foo  
  • 1
如果你想禁止该属性的赋值操作的话(也就是只读),可以不提供setter:

    var obj = {  
  •     __proto__: {  
            get foo() {  
  •             return 1;  
            }  
  •     }  
    };  

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

    > (function () { "use strict"; obj.foo = 2; }());  
  • TypeError: Cannot set property foo of obj which has only a getter
原型链上的只读属性
如果原型链上的起始对象继承了一个只读属性,则你无法通过赋值操作改变这个属性的值.例如,下面的代码:

    var proto = Object.defineProperty({},  
  •     "foo",  
        {  
  •         value: 1,  
            writable: false
  •     });  
  • var obj = { __proto__: proto };
你无法给obj.foo赋值:

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

结帖率:100% (19/19)
发表于 2013-2-4 14:04:29 | 显示全部楼层   江苏省宿迁市
貌似说的很有理的哟。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表