1.对属性操作的控制
在前面我们的属性都是直接定义在对象内部,或者直接添加到对象内部的:
- 但是这样来做的时候我们就不能对这个属性进行一些限制:比如这个属性是否是可以通过delete删除的?这个属性是否在forin遍历的时候被遍历出来呢?
如果我们想要对一个属性进行比较精准的操作控制,那么我们就可以使用属性描述符。
- 通过属性描述符可以精准的添加或修改对象的属性;
- 属性描述符需要使用 Object.defineProperty 来对属性进行添加或者修改;
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor)
可接收三个参数:
- obj要定义属性的对象;
- prop要定义或修改的属性的名称或 Symbol;
- descriptor要定义或修改的属性描述符;
返回值:
- 被传递给函数的对象。
2.属性描述符分类
属性描述符的类型有两种:
2.1 数据属性描述符
数据数据描述符有如下四个特性:
[[Configurable]]:表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符;
-
当我们直接在一个对象上定义某个属性时,这个属性的[[Configurable]]默认为true;
-
当我们通过属性描述符定义一个属性时,这个属性的[[Configurable]]默认为false;
// 直接在一个对象上定义某个属性, 这个属性的Configurable默认为true var obj = { name: "why", age: 18, }; Object.defineProperty(obj, "name", { configurable: false, }); 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()返回该属性;
-
当我们直接在一个对象上定义某个属性时,这个属性的[[Enumerable]]默认为true;
-
当我们通过属性描述符定义一个属性时,这个属性的[[Enumerable]]默认为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]]:表示是否可以修改属性的值;
-
当我们直接在一个对象上定义某个属性时,这个属性的[[Writable]]默认为true;
-
当我们通过属性描述符定义一个属性时,这个属性的[[Writable]]默认为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 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
2.2 存取属性描述符
数据数据描述符有如下四个特性:
-
[[Configurable]]:表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符;
- 和数据属性描述符是一致的;
- 当我们直接在一个对象上定义某个属性时,这个属性的[[Configurable]]默认为true;
- 当我们通过属性描述符定义一个属性时,这个属性的[[Configurable]]默认为false;
-
[[Enumerable]]:表示属性是否可以通过for-in或者Object.keys()枚举返回该属性;
- 和数据属性描述符是一致的;
- 当我们直接在一个对象上定义某个属性时,这个属性的[[Enumerable]]默认为true;
- 当我们通过属性描述符定义一个属性时,这个属性的[[Enumerable]]默认为false;
-
[[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
-
3.同时定义多个属性
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);
},
},
});
4.对象方法补充
获取对象的属性描述符:
-
getOwnPropertyDescriptor
var obj = { name: "why", age: 18, height: 1.88, }; // 获取obj对象name属性的属性描述符 console.log(Object.getOwnPropertyDescriptor(obj, "name"));
-
getOwnPropertyDescriptors
var obj = { name: "why", age: 18, height: 1.88, }; // 获取obj对象中所有属性的属性描述符 console.log(Object.getOwnPropertyDescriptors(obj));
禁止对象扩展新属性:preventExtensions
-
给一个对象添加新的属性会失败(在严格模式下会报错);
var obj = { name: "why", age: 18, height: 1.88, }; // 阻止obj对象扩展属性 Object.preventExtensions(obj) obj.address = "广州市" console.log(obj) // {name: 'why', age: 18, height: 1.88}
密封对象,不允许配置和删除属性:seal
-
实际是调用preventExtensions
-
并且将现有属性的configurable:false
var obj = { name: "why", age: 18, height: 1.88, }; // 将obj对象密封起来(不能进行配置) Object.seal(obj) // obj对象中所有属性都无法删除 delete obj.name delete obj.age console.log(obj) // {name: 'why', age: 18, height: 1.88}
冻结对象,不允许修改现有属性: freeze
-
实际上是调用seal
-
并且将现有属性的writable: false
var obj = { name: "why", age: 18, height: 1.88, }; // 将obj对象冰冻起来(所有属性不允许修改) Object.freeze(obj) // obj对象中所有属性都变成只读 obj.name = "kaisa" obj.age = 20 console.log(obj) // {name: 'why', age: 18, height: 1.88}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120140.html