摘要:今天看你不知道的第五章原型的时候,注意到一个关于属性设置的有意思的地方。但没想到,还有其他不能添加新属性的情况。原型链上有同名的存取器属性,且至少设置了。规则这里以设置为例。那么当我们遇到关于这些知识的的时候,就会很快将问题解决了。
今天看《你不知道的JavaScript》第五章——原型的时候,注意到一个关于JavaScript属性设置的有意思的地方。(P145)
之前,我以为除了对象被设置为不可扩展的情况,其他情况下给对象添加新属性都会成功。但没想到,还有其他不能添加新属性的情况。我所说的这种情况,就是原型链上有与你将要添加的属性同名的属性的时候。
分类原型链上有与你将要添加的属性同名的属性的情况,还要分成三种情况:
原型链上有同名的数据属性并且没有被标记为只读,即writable: true。
原型链上有同名的数据属性,但它被标记为只读,即writable: false。
原型链上有同名的存取器属性,且至少设置了setter。
规则这里以设置myObject.foo = "my"为例。
同名数据属性、可读如果在[[Prototype]]链上层存在名为foo的普通数据访问属性并且没有被标记为只读(wirtable: false),那么就会在myObject中添加一个名为foo的新属性,它就是屏蔽属性。
这种情况是最常见的,下面贴一个简单的例子。
var proObject = { foo: "pro" } var myObject = Object.create(proObject) myObject.foo = "my" myObject.foo // "my" myObject.hasOwnProperty("foo") // true同名数据属性、只读
如果在[[Prototype]]链上层存在foo,但是它被标记为只读(writable: false),那么无法修改已有属性或者在myObject上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。否则,这条赋值语句会被忽略。
var proObject = {} Object.defineProperty(proObject, "foo", { value: "pro", wirtable: false }) var myObject = Object.create(proObject) myObject.foo = "my" myObject.foo // "pro" myObject.hasOwnProperty("foo") // false "use strict" myObject.foo = "my" // Uncaught TypeError: Cannot assign to read only property "foo" of object "#同名的存取器属性
如果在[[Prototype]]链上层存在foo并且它是一个setter,那就一定会调用这个setter。foo不会被添加到(或者说屏蔽于)myObject,也不会重新定义foo这个setter。
var proObject = {} Object.defineProperty(proObject, "foo", { set: function(val) { this.s = val }, get: function() { return this.s } }) myObject.foo = "my" myObject.hasOwnProperty("foo") // false // 可以看到存取器属性没有被重新定义 Object.getOwnPropertyDescriptor(proObject, "foo")解决方案
如果你希望在上述的第二和第三中情况下为myObject添加新属性的话,你需要使用Object.defineProperty或者Object.getOwnPropertyDescriptors来添加新属性。
结语终于在周日完成了这周的博客文章了(虽然很无耻地“水了一篇”,但好歹也算一篇文章嘛。)
正经一点!!!JavaScript中还有很多让我们出乎意料的地方,虽然平时很少遇到这些方面知识的应用,但一旦踩了这些坑,还是会耗掉我们挺多时间和精力的。所以,我们平时应该多留意这些知识,并积累下来。那么当我们遇到关于这些知识的bug的时候,就会很快将问题解决了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/88015.html
摘要:最近刚刚看完了你不知道的上卷,对有了更进一步的了解。你不知道的上卷由两部分组成,第一部分是作用域和闭包,第二部分是和对象原型。附录词法这一章并没有说明机制,只是介绍了中的箭头函数引入的行为词法。第章混合对象类类理论类的机制类的继承混入。 最近刚刚看完了《你不知道的 JavaScript》上卷,对 JavaScript 有了更进一步的了解。 《你不知道的 JavaScript》上卷由两部...
摘要:而在构造函数中,返回了的实例对象。在中直接返回过的实例,这里的是的真正构造函数最后对外暴露入口时,将字符与对等起来。因此当我们直接使用创建一个对象时,实际上是创建了一个的实例,这里的正真构造函数是原型中的方法。 showImg(https://segmentfault.com/img/remote/1460000008749398); 早几年学习前端,大家都非常热衷于研究jQuery源...
阅读 1581·2021-11-16 11:44
阅读 7421·2021-09-22 15:00
阅读 4462·2021-09-02 10:20
阅读 1942·2021-08-27 16:20
阅读 2384·2019-08-26 14:00
阅读 2904·2019-08-26 11:44
阅读 1625·2019-08-23 18:33
阅读 1852·2019-08-22 17:28