资讯专栏INFORMATION COLUMN

js面向对象之屏蔽属性

Pluser / 2777人阅读

摘要:什么是屏蔽属性一条赋值语句引出的思考如果对象中包含名为的普通数据访问属性,这条赋值语句只会修改已有的属性值。然而,如果存在于原型链上层,赋值语句的行为就会有些不同而且可能很出人意料。总之,不会发生屏蔽。

1.什么是屏蔽属性

一条赋值语句引出的思考:

myObject.foo = "bar";

如果myObject 对象中包含名为foo 的普通数据访问属性,这条赋值语句只会修改已有的属
性值。
如果foo 不是直接存在于myObject 中,[[Prototype]] 链就会被遍历,类似[[Get]] 操作。
如果原型链上找不到foo,foo 就会被直接添加到myObject 上。
然而,如果foo 存在于原型链上层,赋值语句myObject.foo = "bar" 的行为就会有些不同
(而且可能很出人意料)。稍后我们会进行介绍。
如果属性名foo 既出现在myObject 中也出现在myObject 的[[Prototype]] 链上层, 那
么就会发生屏蔽。myObject 中包含的foo 属性会屏蔽原型链上层的所有foo 属性,因为
myObject.foo 总是会选择原型链中最底层的foo 属性。

2.屏蔽比我们想象中更加复杂

下面我们分析一下如果foo 不直接存在于myObject 中而是存在于原型链上层时myObject.foo = "bar" 会出现的三种情况。

如果在[[Prototype]] 链上层存在名为foo 的普通数据访问属性并且没有被标记为只读(writable:false),那就会直接在myObject 中添加一个名为foo 的新属性,它是屏蔽属性。

如果在[[Prototype]] 链上层存在foo,但是它被标记为只读(writable:false),那么无法修改已有属性或者在myObject 上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。否则,这条赋值语句会被忽略。总之,不会发生屏蔽。

如果在[[Prototype]] 链上层存在foo 并且它是一个setter(参见第3 章),那就一定会调用这个setter。foo 不会被添加到(或者说屏蔽于)myObject,也不会重新定义foo 这个setter。

3.你所不知道的屏蔽属性

大多数开发者都认为如果向[[Prototype]] 链上层已经存在的属性([[Put]])赋值,就一定会触发屏蔽,但是如你所见,三种情况中只有一种(第一种)是这样的。
如果你希望在第二种和第三种情况下也屏蔽foo,那就不能使用= 操作符来赋值,而是使用Object.defineProperty(..)(参见第3 章)来向myObject 添加foo。

4.JavaScript中的属性:定义和赋值的区别

1.赋值可能会调用原型上的setter(sub与sup里面有同名属性),定义会创建一个自身属性

2.原型链中的同名只读属性可能会阻止赋值操作(如上的非屏蔽操作),但不会阻止定义操作

3.赋值运算符不会改变原型链上的属性

4.只有通过定义操作,才能创建一个拥有指定特性的属性(Object.defineProperty的威力)

5.对象字面量中的属性是通过定义操作添加的

了解更详细的信息可以参考:http://www.cnblogs.com/ziyunf...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88102.html

相关文章

  • JS面向对象的程序设计继承的实现-寄生组合式继承

    摘要:组合继承最大的问题就是无论在什么情况下,都会调用两次超类型构造函数一次是在创建子类型原型的时候。好在,我们已经找到了解决这个问题方法寄生组合式继承所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。 寄生组合式继承 组合继承是JavaScript最常用的继承模式。 不过,它也有自己的不足。 组合继承最大的问题就是无论在什么情况下,都会调用两次超类型构造函数...

    y1chuan 评论0 收藏0
  • 写给Java开发者看的JavaScript对象机制

    摘要:如果你已经对机制已有了解,但是由于两者对象机制的巨大本质差异,对它和构造函数,实例对象的关系仍有疑惑,本文或许可以解答你的问题。所有的原型对象都会自动获得一个属性,这个属性的值是指向原型所在的构造函数的指针。 帮助面向对象开发者理解关于JavaScript对象机制 本文是以一个熟悉OO语言的开发者视角,来解释JavaScript中的对象。 对于不了解JavaScript 语言,尤其是习...

    Charles 评论0 收藏0
  • javascript面向对象继承(上)

    摘要:使用原型链实现对原型属性和方法的继承,用借用构造函数模式实现对实例属性的继承。 我们之前介绍了javascript面向对象的封装的相关内容,还介绍了js的call方法,今天开始讨论js的继承这篇文章参考了《javascript高级程序设计》(第三版),但内容不局限于,网上很多关于js继承的相关内容都是来自于这本书,有兴趣的同学可以翻阅查看 原型链继承 我们先通过一个栗子,了解一下原型链...

    ivyzhang 评论0 收藏0
  • 前端进击的巨人(七):走进面向对象,原型与原型链,继承方式

    摘要:除了以上介绍的几种对象创建方式,此外还有寄生构造函数模式稳妥构造函数模式。 showImg(https://segmentfault.com/img/remote/1460000018196128); 面向对象 是以 对象 为中心的编程思想,它的思维方式是构造。 面向对象 编程的三大特点:封装、继承、多态: 封装:属性方法的抽象 继承:一个类继承(复制)另一个类的属性/方法 多态:方...

    wums 评论0 收藏0
  • 面向对象的程序设计原型模式

    摘要:可以用删除实例对象中自己添加的属性可以确定属性是原型中还是实例对象中,当时实例对象中时,返回的是操作符,有两种使用方式,单独使用和循环中。单独使用,通过对象能够访问属性时返回,无论时在原型中还是实例对象中。 原型模式,每个创建的对象都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。 ------------...

    yunhao 评论0 收藏0

发表评论

0条评论

Pluser

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<