对象属性的操作
定义
我们可以使用属性描述符 对一个属性进行比较精准的操作控制:
- 通过属性描述符可以精准的添加或修改对象的属性
- 需要使用
Object.defineProperty
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor)
三个参数:
- obj要定义属性的对象
- prop要定义或修改的属性的名称或 Symbol
- descriptor要定义或修改的属性描述符
属性描述符
可以看JS 属性描述符
浅谈 JS 对象属性描述符(property descriptor)对象
顾名思义是用来描述属性的。假如有一个对象:
var obj = {
name: "why",
age: 18,
height: 1.88
}
对象里有属性name,我们对它有这样的描述:
对name属性:{
描述1:不能被删除
描述2:不能写入,只能读取
描述3:在获取值时只能获取到why
描述4:在遍历时不要出现
}
这就是属性描述符。
属性描述符分类
- 数据属性 描述符
- 存取属性 描述符
数据属性描述符
Configurable
:表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符.
- 直接在一个对象上定义某个属性,默认true
- 通过属性描述符定义一个属性,默认false
// 直接在一个对象上定义某个属性, 这个属性的Configurable默认为true
var obj = {
name: "why",
age: 18,
};
//把name属性的configurable改为false
Object.defineProperty(obj, "name", {
configurable: false,
});
//则name属性不能通过delete删除
delete obj.name;
console.log(obj); // {name: 'why', age: 18}
// 通过属性描述符定义一个属性, 这个属性的Configurable默认为false
Object.defineProperty(obj, "address", {});
delete obj.address;
console.log(obj); // {name: 'why', age: 18, address: undefined}
Enumerable
:表示属性是否可以通过for-in或者Object.keys()返回该属性
- 直接在一个对象上定义某个属性,默认true
- 通过属性描述符定义一个属性,默认false
// 直接在一个对象上定义某个属性, 这个属性的Configurable默认为true
var obj = {
name: "why",
age: 18,
};
// 告诉JS引擎,obj的name属性不可枚举
Object.defineProperty(obj, "name", {
enumerable: false,
});
// 通过属性描述符定义一个属性, 这个属性的Enumerable默认为false
Object.defineProperty(obj, "address", {});
// 枚举obj
console.log(Object.keys(obj)); // ['age']
Writable
:表示是否可以修改属性的值
- 直接在一个对象上定义某个属性,默认true
- 通过属性描述符定义一个属性,默认false
// 直接在一个对象上定义某个属性, 这个属性的Writable默认为true
var obj = {
name: "why",
age: 18,
};
// 告诉JS引擎obj的name属性是不可修改的, 不可写入(只读)
Object.defineProperty(obj, "name", {
writable: false,
});
// 通过属性描述符定义一个属性, 这个属性的Writable默认为false
Object.defineProperty(obj, "address", {});
obj.name = "kaisa";
console.log(obj.name); // why 因为name不可改
obj.address = "成都市";
console.log(obj.address); // undefined //默认不可改
value
:属性的value值,读取属性时会返回该值,修改属性时,会对其进行修改,默认是undefined
var obj = {
name: "why",
age: 18,
};
// 告诉JS引擎, 读取obj的name属性会返回kaisa这个值
Object.defineProperty(obj, "name", {
value: "kaisa",
});
console.log(obj.name); // kaisa
存取属性描述符
Configurable
、Enumerable
与数据数据描述符的相同。
set
:设置属性时就会执行的函数。默认为undefined。当获取属性时, 就会执行set函数。
var obj = {
name: "why",
age: 18,
};
// 当设置name属性的时候, 就会调用set函数
Object.defineProperty(obj, "name", {
set: function (value) {
console.log("set方法被调用了", value);
},
});
obj.name = "kaisa"; // set方法被调用了 kaisa
obj.name = "vn"; // set方法被调用了 vn
get
:获取属性时就会执行的函数。默认为undefined。当获取属性时, 就会执行get函数。
var obj = {
name: "why",
age: 18,
};
var _name = "";
// 当设置name属性的时候, 就会调用set函数
Object.defineProperty(obj, "name", {
set: function (value) {
console.log("set函数被调用了", value);
_name = value;
},
get: function () {
console.log("get函数被调用了");
return _name;
},
});
obj.name = "kaisa"; // set方法被调用了 kaisa
console.log(obj.name); // get函数被调用了 kaisa
obj.name = "vn"; // set方法被调用了 vn
console.log(obj.name); // get函数被调用了 vn
同时定义多个属性
Object.defineProperties()
方法直接在一个对象上定义多个新的属性描述符或修改现有属性,并且返回该对象:
var obj = {
name: "why",
age: 18,
height: 1.88,
};
Object.defineProperties(obj, {
name: {
configurable: true,
},
age: {
configurable: false,
writable: false,
},
height: {
set: function (value) {
console.log("set函数被调用", value);
},
},
});
其他对象方法(了解)
获取对象的属性描述符:getOwnPropertyDescriptor
获取对象所有属性的描述符:getOwnPropertyDescriptors
禁止对象扩展新属性:preventExtensions
——给一个对象添加新的属性会失败(在严格模式下会报错)
密封对象,不允许配置和删除属性:seal
- 实际是调用
preventExtensions
- 将现有属性的
configurable:false
冻结对象,不允许修改现有属性:freeze
- 实际上是调用
seal
- 将现有属性的
writable: false
参考
coderwhy的课
JavaScript对象的增强、属性描述符介绍
JS 属性描述符
浅谈 JS 对象属性描述符(property descriptor)对象