前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js Object.defineProperty()详解

js Object.defineProperty()详解

原创
作者头像
IT工作者
发布2022-05-12 17:09:04
2.4K0
发布2022-05-12 17:09:04
举报
文章被收录于专栏:程序技术知识

要修改属性的默认特性,就必须使用 Object.defineProperty()方法 ;在了解Object.defineProperty()之前,需要先明白对象属性的一些特性,明白了这些特性之后,对Object.defineProperty()的学习就会顺利很多了。

1. 属性的类型

ECMA-262 使用一些内部特性来描述属性的特征。这些特性是由为JavaScript 实现引擎的规范定义的。因此,开发者不能在 JavaScript 中直接访问这些特性。

属性分两种:数据属性和访问器属性。

1.1 数据属性

数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有 4个特性描述它们的行为:

Configurable:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,所有直接定义在对象上的属性的这个特性都是 true;

Enumerable:表示属性是否可以通过 for-in 循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是 true;

Writable: 表示属性的值是否可以被修改。默认情况下,所有直接定义在对象上的属性的这个特性都是 true;

Value:包含属性实际的值。这就是前面提到的那个读取和写入属性值的位置。这个特性的默认值为 undefined。

1.2 访问器属性

访问器属性不包含数据值。相反,它们包含一个获取(getter)函数和一个设置(setter)函数。在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。访问器属性有 4 个特性描述它们的行:

Configurable:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性。默认情况下,所有直接定义在对象上的属性的这个特性都是 true;

Enumerable: 表示属性是否可以通过 for-in 循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是 true;

Get: 获取函数,在读取属性时调用。默认值为 undefined;

Set:设置函数,在写入属性时调用。默认值为 undefined。

2. Object.defineProperty()

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象;

语法: Object.defineProperty(object,prop,descript)

Object.defineProperty()接收三个参数:

object: 要添加或者修改属性的目标对象;

prop: 要定义或修改属性的名称;

descript: 是一个对象,里面是我们上述的对象属性的特性;

下面我们使用Object.defineProperty()分别演示数据属性和访问器属性;

注意:数据属性和访问器属性不能同时设置,也就是数据属性的writable和value不能和访问器属性的set和get同时设置,否则会报错。

3. Object.defineProperty设置数据属性

3.1 Configurable

注意: 如果该属性被定义为不可配置(false)之后,就不能再变回可配置的了,否则会报错。

代码语言:javascript
复制
const person = {
    name: 'lc',
};
// 定义新属性
Object.defineProperty(person, "age", {
    configurable: false, // configurable 设置为 false,意味着这个属性不能从对象上删除
    value: 25 // 设置age的值,不设置的话默认为undefined 后续不再演示value
});
console.log(person.age); // 25 
delete person.age; // 因为configurable设置为false,所以无法删除该属性
console.log(person.age); // 25

// 修改已有属性
Object.defineProperty(person, "name", {
    configurable: false,
    value: "小明"
});
console.log(person.name); // 小明 value属性将值修改
delete person.name; // 因为configurable设置为false,所以无法删除该属性
console.log(person.name); // 小明

3.2 Enumerable

代码语言:javascript
复制
const person = {
    name: 'lc',
    age: 20
};
Object.defineProperty(person, "age", {
    enumerable: false // 设置为false表示不能通过 for-in 循环返回
});

for (const i in person) {
    console.log(i);
}
// 结果: name

3.3 Writable

代码语言:javascript
复制
const person = {
    name: "lc"
};
Object.defineProperty(person, "name", {
    writable: false // 表示属性的值不可以被修改
});

console.log(person.name); // lc
person.name = "小明"; // 修改无效
console.log(person.name); // lc

3.4 注意

在调用 Object.defineProperty()时,configurable、enumerable 和 writable 的值如果不指定,则都默认为 false。

代码语言:javascript
复制
const person = {};
Object.defineProperty(person, "name", {}); 
//configurable、enumerable 和 writable 的值未指定,则都默认为 false。

4. Object.defineProperty设置访问器属性

Configurable 和 Enumerable和上述一样,这里不再演示。

4.1 Get、Set

get: 获取函数,在读取属性时调用。默认值为 undefined;

set: 设置函数,在写入属性时调用。默认值为 undefined。

代码语言:javascript
复制
const book = { 
    year_: 2022, 
    edition: 1
};
Object.defineProperty(book, "year", { 
    get() { 
        return this.year_; 
    }, 
    set(newValue) { 
        if (newValue > 2022) { 
            this.year_ = newValue; 
            this.edition += newValue - 2022; 
        } 
    } 
}); 
book.year = 2021; 
console.log(book.edition); // 2 

5. 定义多个属性Object.defineProperties()

在一个对象上同时定义多个属性的可能性是非常大的。为此,ECMAScript 提供了 Object.defineProperties()方法。这个方法可以通过多个描述符一次性定义多个属性。它接收两个参数:要为之添加或修改属性的对象和另一个描述符对象,其属性与要添加或修改的属性一一对应:

代码语言:javascript
复制
const book= {};
Object.defineProperties(person, {
    year_: {
        value: 2022
    },
    edition: {
        value: 1
    },
    year: {
        get() {
            return this.year_;
        },
        set(newValue) { 
            if (newValue > 2022) { 
                this.year_ = newValue; 
                this.edition += newValue - 2022; 
            } 
        } 
    },    
})

6. 读取属性的特性Object.getOwnPropertyDescriptor()

Object.getOwnPropertyDescriptor()方法接收两个参数:属性所在的对象和要取得其描述符的属性名,返回值是一个对象:

代码语言:javascript
复制
const person = {
    name: 'lc'
};
console.log(Object.getOwnPropertyDescriptor(person, "name"));
// { configurable: true, enumerable: true, value: "lc", writable: true }

7. 获取所有属性的特性 getOwnPropertyDescriptors()

ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors()静态方法。这个方法实际上会在每个自有属性上调用 Object.getOwnPropertyDescriptor()并在一个新对象中返回它们:

代码语言:javascript
复制
const person = { 
    name: "lc",
    age: 22
};
console.log(Object.getOwnPropertyDescriptors(person));

结果如下:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档