js面向对象之屏障属性

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” 会涌现的三种状况。

  1. 假如在[[Prototype]] 链上层存在名为foo 的一般数据接见属性而且没有被标记为只读(writable:false),那就会直接在myObject 中增加一个名为foo 的新属性,它是屏障属性。
  2. 假如在[[Prototype]] 链上层存在foo,然则它被标记为只读(writable:false),那末没法修正已有属性或许在myObject 上建立屏障属性。假如运行在严厉形式下,代码会抛出一个毛病。不然,这条赋值语句会被疏忽。总之,不会发作屏障。
  3. 假如在[[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…

    原文作者:specialCoder
    原文地址: https://segmentfault.com/a/1190000008142704
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞