ECMA-262 使用两个中括号把特性的名称括起来,将某个特性标识为内部特性,例如 [[Enumerable]]
数据属性
1 2 3 4 5
| let book = { year_: 2017, edition: 1 };
|
访问器属性
Object.defineProperties() 方法可以通过多个描述符一次性定义多个属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| let book = {}; Object.defineProperties(book, {
year_: { value: 2017 },
edition: { value: 1 },
year: { get() { return this.year_; },
set(newValue) { if(newValue > 2017) { this.year_ = newValue; this.edition += newValue - 2017; } } } });
|
使用 Object.getOwnPropertyDescriptor() 方法可以取得指定属性的属性描述符
该方法接收属性所在的对象和要取得其描述符的属性名
访问器属性返回包含 configurable、enumerable、get 和 set 属性的对象
数据属性返回包含 configurable、enumerable、writable 和 value 属性的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| let book = {};
Object.defineProperties(book, { year_: { value: 2017 },
edition: { value: 1 },
year: { get: function() { return this.year_; },
set: function(newValue) { if (newValue > 2017) { this.year_ = newValue; this.edition += newValue - 2017; } } } });
let descriptor = Object.getOwnPropertyDescriptor(book, 'year_'); console.log(descriptor.value); console.log(descriptor.configurable); console.log(typeof descriptor.get);
descriptor = Object.getOwnPropertyDescriptor(book, 'year'); console.log(descriptor.value); console.log(descriptor.enumerable); console.log(typeof descriptor.get);
console.log(Object.getOwnPropertyDescriptors(book));
|
Object.assign() 方法用于合并对象
该方法接收一个目标对象和一个或多个源对象作为参数,然后将每个源对象中可枚举(Object.propertyIsEnumerable() 返回 true) 和自有(Object.hasOwnProperty() 返回 true)属性复制到目标对象
该方法会复制以字符串和符号为键的属性
对每个符合条件的属性,该方法会使用源对象上的 [[Get]] 取得属性的值,然后使用目标对象上的 [[Set]] 设置属性的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| dest = { set a(val) { console.log(`Invoked dest setter with param ${val}`); } };
src = { get a() { console.log('Invoked src getter'); return 'foo'; } };
Object.assign(dest, src);
console.log(dest);
|
Object.assign() 对每个源对象执行浅复制(1.直接复制对象的基本类型值 2.引用类型数据只复制内存地址,新旧对象共享同一份深层数据,修改深层数据会相互影响)。如果多个源对象有相同的属性,则使用最后一个复制的值
如果赋值期间出错,操作会中止并退出,同时抛出错误
Object.is() 判定相等
Object.is() 与 === 类似,但能正确处理特殊值
Object.is(NaN, NaN) 返回 true(而 NaN === NaN 返回 false)
Object.is(+0, -0) 返回 false(而 +0 === -0 返回 true)
增强的对象语法
简写属性名
简写属性名只要使用变量名(不用再写冒号)就会自动被解释为同名的属性键。如果没有找到同名变量,则会抛出 ReferenceError
下面两段代码等价
1 2 3 4 5 6 7
| let name = 'Matt';
let person = { name: name };
console.log(person);
|
1 2 3 4 5 6 7
| let name = 'Matt';
let person = { name };
console.log(person);
|
可计算属性
可计算属性可以在对象字面量中完成动态属性赋值,不用先声明对象,再使用中括号语法来添加属性
1 2 3 4 5 6 7 8 9 10 11 12
| const nameKey = 'name'; const ageKey = 'age'; const jobKey = 'job';
let person = { [nameKey]: 'Matt', [ageKey]: 27, [jobKey]: 'Software engineer' };
console.log(person);
|
对象解构
对象解构就是使用与对象匹配的结构来实现对象属性赋值,可以在一个类似对象字面量的结构中,声明多个变量,同时执行多个赋值操作。
如果引用的属性不存在,则该变量的值就是 undefined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let person = { name: 'Matt', age: 27 };
let { name: personName, age: personAge } = person;
console.log(personName); console.log(personAge);
let { name, job } = person;
console.log(name); console.log(job);
|
1 2 3 4 5 6 7 8 9 10 11
| let { length } = 'foobar';
console.log(length);
let { constructor: c } = 4; console.log(c === Number);
let { _ } = null; let { _0 } = undefined;
|
如果给事先声明的变量赋值,则赋值表达式必须包含在一对括号中
1 2 3 4 5 6 7 8 9 10 11
| let personName, personAge;
let person = { name: 'Matt', age: 27 };
({name: personName, age: personAge} = person);
console.log(personName, personAge);
|
解构赋值可以使用嵌套解构,以匹配嵌套的属性
1 2 3 4 5 6 7 8 9 10 11
| let person = { name: 'Matt', age: 27, job: { title: 'Software Engineer' } };
let { job: { title } } = person; console.log(title);
|