资讯专栏INFORMATION COLUMN

一个你可能没有注意到的关于JavaScript属性设置的知识

lovXin / 2720人阅读

摘要:今天看你不知道的第五章原型的时候,注意到一个关于属性设置的有意思的地方。但没想到,还有其他不能添加新属性的情况。原型链上有同名的存取器属性,且至少设置了。规则这里以设置为例。那么当我们遇到关于这些知识的的时候,就会很快将问题解决了。

今天看《你不知道的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

相关文章

  • 前端知识点整理

    摘要:难怪超过三分之一的开发人员工作需要一些知识。但是随着行业的饱和,初中级前端就业形势不容乐观。整个系列的文章大概有篇左右,从我是如何成为一个前端工程师,到各种前端框架的知识。 为什么 call 比 apply 快? 这是一个非常有意思的问题。 作者会在参数为3个(包含3)以内时,优先使用 call 方法进行事件的处理。而当参数过多(多余3个)时,才考虑使用 apply 方法。 这个的原因...

    Lowky 评论0 收藏0
  • 前端知识点整理

    摘要:难怪超过三分之一的开发人员工作需要一些知识。但是随着行业的饱和,初中级前端就业形势不容乐观。整个系列的文章大概有篇左右,从我是如何成为一个前端工程师,到各种前端框架的知识。 为什么 call 比 apply 快? 这是一个非常有意思的问题。 作者会在参数为3个(包含3)以内时,优先使用 call 方法进行事件的处理。而当参数过多(多余3个)时,才考虑使用 apply 方法。 这个的原因...

    snowLu 评论0 收藏0
  • 【译】前端练级攻略

    摘要:由于系统变得越来越复杂,人们提出了称为预处理器和后处理器的工具来管理复杂性。后处理器在由预处理器手写或编译后对应用更改。我之前建议的文章,,也涵盖了预处理器相关的知识。 译者:前端小智 原文:medium.freecodecamp.org/from-zero-t… medium.freecodecamp.org/from-zero-t… 我记得我刚开始学习前端开发的时候。我看到了很多文章及...

    wuyumin 评论0 收藏0
  • 十分钟快速了解《不知道 JavaScript》(上卷)

    摘要:最近刚刚看完了你不知道的上卷,对有了更进一步的了解。你不知道的上卷由两部分组成,第一部分是作用域和闭包,第二部分是和对象原型。附录词法这一章并没有说明机制,只是介绍了中的箭头函数引入的行为词法。第章混合对象类类理论类的机制类的继承混入。 最近刚刚看完了《你不知道的 JavaScript》上卷,对 JavaScript 有了更进一步的了解。 《你不知道的 JavaScript》上卷由两部...

    赵春朋 评论0 收藏0
  • 前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery插件

    摘要:而在构造函数中,返回了的实例对象。在中直接返回过的实例,这里的是的真正构造函数最后对外暴露入口时,将字符与对等起来。因此当我们直接使用创建一个对象时,实际上是创建了一个的实例,这里的正真构造函数是原型中的方法。 showImg(https://segmentfault.com/img/remote/1460000008749398); 早几年学习前端,大家都非常热衷于研究jQuery源...

    RebeccaZhong 评论0 收藏0

发表评论

0条评论

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