JS对象属性除了键值对还藏着属性标识你知道吗?

652 阅读3分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

我们知道,对象可以存储属性。属性看上去好像只是一个简单的“键值”对。但对象属性实际上是更灵活且更强大的东西。现在我们就来深入了解一下。

属性标志

介绍之前,我们先来学习一个方法,这个方法可以查询有关属性 完整 信息。

语法:Object.getOwnPropertyDescriptor(obj, prop)

参数:
obj  需要查找的目标对象
prop 目标对象内属性名称

返回值
返回值是一个所谓的“属性描述符”对象:它包含值和所有的标志。

实例:

image-20211113101423543

从上面可以看到,我们给user对象写了一个name属性,但是我们除了获取到属性的值value 之外,还有三个特殊的特性(attributes),也就是所谓的“标志”。

  • writable — 如果为 true,则值可以被修改,否则它是只可读的。
  • enumerable — 如果为 true,则会被在循环中列出,否则不会被列出。
  • configurable — 如果为 true,则此特性可以被删除,这些属性也可以被修改,否则不可以。

正常创建一个属性时,这些标志的值都为true

修改标志

当然,这些标志也是可修改的

语法:Object.defineProperty(obj, propertyName, descriptor)

obj和propertyName:要应用描述符的对象及其属性。
descriptor:要应用的属性描述符对象。

标志的影响

只读

现在我们来看看标志都有些什么影响;

先来看一个示例:

image-20211114222631505

我们通过更改 writable 标志来把 user.name 设置为只读(user.name 不能被重新赋值),现在没有人可以改变我们 username,除非它们应用自己的 defineProperty 来覆盖我们的 username

注意:这个错误只有在严格模式下才会出现。

不可枚举

对象的属性,默认值可枚举的

image-20211114223129011

但是可以设置 enumerable:false,某属性不被枚举

Object.defineProperty(user, "age", {
  enumerable: false
});

image-20211114223624028

不可枚举的属性,除了 for..in 循环中不会被显示之外,也会被 Object.keys 排除

Object.keys(user) // name

不可配置

  • 不可配置标志(configurable:false)有时会预设在内建对象和属性中。
  • 不可配置的属性不能被删除。

示例:Math.PI 就是只读的、不可枚举和不可配置的

image-20211114223910805

所以这就是为什么,你是不能直接修改Math.PI 的(当然,这是在严格模式下的情况)

image-20211114224035983

"configurable: false" 的用途是防止更改和删除属性标志,但是允许更改对象的值。

如果你新建了一个对象,只设置了configurable: false,那么属性值仍然可以修改,但是不能被删除

image-20211114224717982

扩展

一次定义多个属性,可以使用 Object.defineProperties(obj, descriptors)

语法:

Object.defineProperties(obj, {
  prop1: descriptor1,
  prop2: descriptor2
  // ...
});

示例:

Object.defineProperties(user, {
  name: { value: "John", writable: false },
  surname: { value: "Smith", writable: false },
  // ...
});

设定全局加密封对象

属性描述符在单个属性的级别上工作,还有一些限制访问 整个 对象的方法,虽然比较少用到,但是可以了解一下

语法描述
Object.preventExtensions(obj)禁止向对象添加新属性。
Object.seal(obj)禁止添加/删除属性。为所有现有的属性设置 configurable: false
Object.freeze(obj)禁止添加/删除/更改属性。为所有现有的属性设置 configurable: false, writable: false

还提供给了一些方法,查看上面的设置是否生效

语法描述
Object.isExtensible(obj)如果添加属性被禁止,则返回 false,否则返回 true
Object.isSealed(obj)如果添加/删除属性被禁止,并且所有现有的属性都具有 configurable: false则返回 true
Object.isFrozen(obj)如果添加/删除/更改属性被禁止,并且所有当前属性都是 configurable: false, writable: false,则返回 true

参考资料:

MDN getOwnPropertyDescriptor

MDN defineProperty

Property flags and descriptors


🎨【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

👉 产品、技术、设计等各互联网领域的「基础术语」扫盲

👉 Web安全的防御手段都在这里了!

👉 JavaScript的7大类型补缺补漏!

👉 JavaScript深拷贝和浅拷贝看这篇就够了!