Object.defineProperty()

您所在的位置:网站首页 javascript定义一个函数 Object.defineProperty()

Object.defineProperty()

2023-10-06 05:01| 来源: 网络整理| 查看: 265

Object.defineProperty() 允许精确地添加或修改对象上的属性。通过赋值添加的普通属性会在枚举属性时(例如 for...in、Object.keys() 等)出现,它们的值可以被更改,也可以被删除。此方法允许更改这些额外细节,以使其不同于默认值。默认情况下,使用 Object.defineProperty() 添加的属性是不可写、不可枚举和不可配置的。此外,Object.defineProperty() 使用 [[DefineOwnProperty]] 内部方法,而不是 [[Set]],因此即使属性已经存在,它也不会调用 setter。

对象中存在的属性描述符有两种主要类型:数据描述符和访问器描述符。数据描述符是一个具有可写或不可写值的属性。访问器描述符是由 getter/setter 函数对描述的属性。描述符只能是这两种类型之一,不能同时为两者。

数据描述符和访问器描述符都是对象。它们共享以下可选键(请注意:在使用 Object.defineProperty() 定义属性的情况下,下述所有键都是默认值):

configurable

当设置为 false 时,

该属性的类型不能在数据属性和访问器属性之间更改,且 该属性不可被删除,且 其描述符的其他属性也不能被更改(但是,如果它是一个可写的数据描述符,则 value 可以被更改,writable 可以更改为 false)。

默认值为 false。

enumerable

当且仅当该属性在对应对象的属性枚举中出现时,值为 true。默认值为 false。

数据描述符还具有以下可选键值:

value

与属性相关联的值。可以是任何有效的 JavaScript 值(数字、对象、函数等)。默认值为 undefined。

writable

如果与属性相关联的值可以使用赋值运算符更改,则为 true。默认值为 false。

访问器描述符还具有以下可选键值:

get

用作属性 getter 的函数,如果没有 getter 则为 undefined。当访问该属性时,将不带参地调用此函数,并将 this 设置为通过该属性访问的对象(因为可能存在继承关系,这可能不是定义该属性的对象)。返回值将被用作该属性的值。默认值为 undefined。

set

用作属性 setter 的函数,如果没有 setter 则为 undefined。当该属性被赋值时,将调用此函数,并带有一个参数(要赋给该属性的值),并将 this 设置为通过该属性分配的对象。默认值为 undefined。

如果描述符没有 value、writable、get 和 set 键中的任何一个,它将被视为数据描述符。如果描述符同时具有 [value 或 writable] 和 [get 或 set] 键,则会抛出异常。

这些属性不一定是描述符本身的属性。继承的属性也会被考虑在内。为了确保这些默认值得到保留,你可以预先冻结描述符对象原型链中的现有对象,明确指定所有选项,或使用 Object.create(null) 指向 null。

js

const obj = {}; // 1. 使用 null 原型:没有继承的属性 const descriptor = Object.create(null); descriptor.value = "static"; // 默认情况下,它们不可枚举、不可配置、不可写 Object.defineProperty(obj, "key", descriptor); // 2. 使用一个包含所有属性的临时对象字面量来明确其属性 Object.defineProperty(obj, "key2", { enumerable: false, configurable: false, writable: false, value: "static", }); // 3. 重复利用同一对象 function withValue(value) { const d = withValue.d || (withValue.d = { enumerable: false, writable: false, configurable: false, value, }); // 避免重复赋值 if (d.value !== value) d.value = value; return d; } // 然后 Object.defineProperty(obj, "key", withValue("static")); // 如果 freeze 可用,防止添加或删除对象原型属性 // (value、get、set、enumerable、writable、configurable) (Object.freeze || Object)(Object.prototype);

当属性已经存在时,Object.defineProperty() 会尝试根据描述符和属性的当前配置修改属性。

如果旧描述符的 configurable 特性被设置为 false,则该属性被称为不可配置的。无法更改不可配置的访问器属性的任何特性,也不能将其在数据类型和访问器类型之间切换。对于具有 writable: true 的数据属性,可以修改其值并将 writable 特性从 true 改为 false。当试图更改不可配置的属性(除非允许更改 value 和 writable)时,会抛出 TypeError,除非在数据属性上定义一个与原始值相同的值。

当当前属性是可配置的时,将特性设置为 undefined 可以有效地删除它。例如,如果 o.k 是一个访问器属性,Object.defineProperty(o, "k", { set: undefined }) 将删除 setter,使 k 只有 getter 并变成只读的。如果新描述符中缺少一个特性,则会保留旧描述符该特性的值(不会被隐式重新设置为 undefined)。通过提供不同类型的描述符,可以在数据属性和访问器属性之间切换。例如,如果新描述符是数据描述符(带有 value 或 writable),则原始描述符的 get 和 set 属性都将被删除。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3