1. Object.defineProperty()
Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
备注:应当直接在 Object 构造器对象上调用此方法,而不是在任意一个 Object 类型的实例上调用。
语法:
Object.defineProperty(obj, prop, descriptor)
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。
例子
在我们平常的使用中,给对象添加一个属性时,直接使用object.param的方式就可以了,或者直接在对象中挂载。
const person = { name: 'hj' }
在ECMAScript5中,对每个属性都添加了几个属性类型,来描述这些属性的特点。他们分别是
configurable: 默认false
configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
当第一次设置为false后,再改写是不可以的。属性值也是不能被删除的。
var o = {}; Object.defineProperty(o, 'a', { get() { return 1; }, configurable: false }); // 定义为false 后 enumerable set get configurable value 都是不能再设置了。 delete o.a 也是删不了的 Object.defineProperty(o, 'a', { configurable: true }); // throws a TypeError 抛出错误 Object.defineProperty(o, 'a', { enumerable: true }); // 抛出错误 Object.defineProperty(o, 'a', { set() {} }); // 报错 Object.defineProperty(o, 'a', { get() { return 1; } }); // throws a TypeError // (even though the new get does exactly the same thing) Object.defineProperty(o, 'a', { value: 12 }); // throws a TypeError // ('value' can be changed when 'configurable' is false but not in this case due to 'get' accessor) console.log(o.a); // logs 1 delete o.a; // Nothing happens console.log(o.a); // logs 1 还存在说明没删掉
enumerable: 默认false
enumerable 定义了对象的属性是否可以在 for…in 循环和 Object.keys() 中被枚举。
for…in 循环和 Object.keys() 定义: 任意顺序遍历一个对象的除Symbol以外的可枚举属性。
var o = {}; Object.defineProperty(o, "a", { value : 1, enumerable: true }); Object.defineProperty(o, "b", { value : 2, enumerable: false }); Object.defineProperty(o, "c", { value : 3 }); // enumerable 默认为 false o.d = 4; // 如果使用直接赋值的方式创建对象的属性,则 enumerable 为 true Object.defineProperty(o, Symbol.for('e'), { value: 5, enumerable: true }); Object.defineProperty(o, Symbol.for('f'), { value: 6, enumerable: false }); for (var i in o) { console.log(i); } // 只会打印a 和 d Object.keys(o); // ['a', 'd']
打印 对象 o 在谷歌浏览器中查看

o.propertyIsEnumerable('a'); // true o.propertyIsEnumerable('b'); // false o.propertyIsEnumerable('c'); // false o.propertyIsEnumerable('d'); // true o.propertyIsEnumerable(Symbol.for('e')); // true o.propertyIsEnumerable(Symbol.for('f')); // false var p = { ...o } p.a // 1 p.b // undefined p.c // undefined p.d // 4 p[Symbol.for('e')] // 5 p[Symbol.for('f')] // undefined
writable: 默认false
当 writable 属性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值。
var o = {}; // 创建一个新对象 Object.defineProperty(o, 'a', { value: 37, writable: false }); console.log(o.a); // 37 o.a = 25; // No error thrown 不会抛出错误,但是也更改不了这个值,因为这个不是在严格模式下 // (it would throw in strict mode, // even if the value had been the same) console.log(o.a); // 还是37 // strict mode (function() { 'use strict'; var o = {}; Object.defineProperty(o, 'b', { value: 2, writable: false }); o.b = 3; // throws TypeError: "b" is read-only return o.b; // returns 2 without the line above }());
- value : 默认undefined
如果对象中不存在指定的属性,
Object.defineProperty()会创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。
var o = {}; // 创建一个新对象 // 在对象中添加一个属性与数据描述符的示例 Object.defineProperty(o, "a", { value : 37, writable : true, enumerable : true, configurable : true }); // 对象 o 拥有了属性 a,值为 37 // 在对象中添加一个设置了存取描述符属性的示例 var bValue; Object.defineProperty(o, "b", { // 使用了方法名称缩写(ES2015 特性) // 下面两个缩写等价于: // get : function() { return bValue; }, // set : function(newValue) { bValue = newValue; }, get() { return bValue; }, set(newValue) { bValue = newValue; }, enumerable : true, configurable : true }); o.b; // 38 // 对象 o 拥有了属性 b,值为 38 // 现在,除非重新定义 o.b,o.b 的值总是与 bValue 相同 // 数据描述符和存取描述符不能混合使用 Object.defineProperty(o, "conflict", { value: 0x9f91102, get() { return 0xdeadbeef; } }); // 抛出错误 TypeError: value appears only in data descriptors, get appears only in accessor descriptors
get: 当我们通过person.name访问name的值时,get将被调用。该方法可以自定义返回的具体值是多少。get默认值为undefinedset: 当我们通过person.name = 'Jake'设置name的值时,set方法将被调用。该方法可以自定义设置值的具体方式。set默认值为undefined
考虑特性被赋予的默认特性值非常重要,通常,使用点运算符和
Object.defineProperty()为对象的属性赋值时,数据描述符中的属性默认值是不同的
var o = {}; o.a = 1; // 默认做了下边这件事,等同于: Object.defineProperty(o, "a", { value: 1, writable: true, configurable: true, enumerable: true }); // 如果这样定义, Object.defineProperty(o, "a", { value : 1 }); // 默认做了下边这件事,等同于: Object.defineProperty(o, "a", { value: 1, writable: false, configurable: false, enumerable: false });
需要注意的是,不能同时设置value、writable 与 get、set的值。
var person = {} // 通过get与set自定义访问与设置name属性的方式 Object.defineProperty(person, 'name', { get: function() { // 一直返回TOM return 'TOM' }, set: function(value) { // 设置name属性时,返回该字符串,value为新值 console.log(value + ' in set'); } }) // 第一次访问name,调用get console.log(person.name) // TOM // 尝试修改name值,此时set方法被调用 person.name = 'alex' // alex in set // 第二次访问name,还是调用get console.log(person.name) // TOM
请尽量同时设置get、set。如果仅仅只设置了get,那么我们将无法设置该属性值。如果仅仅只设置了set,我们也无法读取该属性的值。
2.Object.defineProperties
当我们想要同时设置多个属性的特性时,需要使用Object.defineProperties
语法:
Object.defineProperties(obj, props)
参数说明
obj在其上定义或修改属性的对象。
props要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。描述符具有以下键:
configurable
true当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。
默认为false
enumerable
true当且仅当在枚举相应对象上的属性时该属性显现。
默认为false
value
writable
true当且仅当与该属性相关联的值可以用assignment operator改变时。
默认为false
get
set
用法除了格式基本与Object.defineProperty相同
var person = {} Object.defineProperties(person, { name: { value: 'Jake', configurable: true }, age: { get: function() { return this.value || 22 }, set: function(value) { this.value = value } } }) person.name // Jake person.age // 22
读取属性的特性值
我们可以使用Object.getOwnPropertyDescriptor方法读取某一个属性的特性值。
var person = {} Object.defineProperty(person, 'name', { value: 'alex', writable: false, configurable: false }) var descripter = Object.getOwnPropertyDescriptor(person, 'name'); console.log(descripter); // 返回结果如下 descripter = { configurable: false, enumerable: false, value: 'alex', writable: false }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216991.html原文链接:https://javaforall.net
