ES6总结系列之 对象的扩展 篇


1. 属性、方法简洁表示法

属性简写

const foo = 'bar';

const baz = {foo}; //属性名就是变量名, 属性值就是变量值
baz // {foo: "bar"}

// 等同于
const baz = {foo: foo};

方法简写

const obj = {
  method () {
    return 'Hello!'
  }
}

//等同于
const obj = {
  method: function () {
    return 'Hello!'
  }
}

简写的对象方法不能用作构造函数,会报错。

const obj = {
  f() {
    this.foo = 'bar';
  }
};

new obj.f() // 报错

2. 属性名表达式

JavaScript 定义对象的属性,有两种方法。

// 方法一
obj.foo = true;
//直接用标识符作为属性名

// 方法二
obj['a' + 'bc'] = 123;
//用表达式作为属性名,须将表达式放在方括号之内

①使用字面量方式定义对象(使用大括号),在 ES5 中只能使用方法一(标识符)定义属性。ES6 允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在方括号内。

let lastWord = 'last word';

const a = {
  'first word': 'hello',
  [lastWord]: 'world'
};

a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"

②表达式还可以用于定义方法名

let obj = {
  ['h' + 'ello']() {
    return 'hi';
  }
};

obj.hello() // hi

③属性名表达式与简洁表示法,不能同时使用

// 报错
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };

// 正确
const foo = 'bar';
const baz = { [foo]: 'abc'};

④属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object],这一点要特别小心。

const keyA = {a: 1};
const keyB = {b: 2};

const myObject = {
  [keyA]: 'valueA',
  [keyB]: 'valueB'
};

myObject // Object {[object Object]: "valueB"}

3.属性的可枚举和遍历

可枚举性

①每个对象都有一个描述对象(Descriptor),来控制属性的行为
②用Object.getOwnPropertyDescriptor ()来获取

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
	//    value: 123,
	//    writable: true,
	//    enumerable: true,
	//    configurable: true
//  }

③enumerable为false时,为不可枚举,四种操作会忽略enumerable为false的属性
1)for...in 循环 返回自身和继承的可枚举属性
2)Object.keys(obj) 返回可枚举的key数组
3)JSON.stringify() 串化可枚举的属性
4)Object.assign() 拷贝自身可枚举的属性
5)其中只有 for...in 会遍历继承的属性,其他只遍历自身属性

属性的遍历

④五种属性的遍历
1)for…in
2)Object.keys(obj) 返回数组
3)Object.getOwnPropertyNames(obj) 返回数组
4)Object.getOwnPropertySymbols(obj) 返回数组
5)Reflect.ownKeys(obj) 返回数组
6)(1)(2)(3)不含Symbol属性,(4)(5)含Symbol属性,(3)(5)包含不可枚举属性
⑤遍历顺序
数值键 --> 字符串键 --> Symbol键
(数值升序) - (时间升序) - (时间升序)

4.super关键字

1)指向对象原型
2)只能用在对象的方法中
3)只能用在对象简写法可以让JavaScript引擎确认,定义的是对象的方法

const proto = {
  foo: 'hello'
};

const obj = {
  foo: 'world',
  find() {
    return super.foo;
  }
};

Object.setPrototypeOf(obj, proto);
obj.find() // "hello"

5.对象的扩展运算符

1)解构赋值要求求等号右边是一个对象,所以如果等号右边是undefined或null,就会报错,因为它们无法转为对象
2)扩展运算符的解构赋值不能复制继承制原型对象上的属性
3)let { x, …{ y, z } } = o; 错误
4)解构赋值的拷贝是浅拷贝
5)如果有取值函数get,这个函数是会执行的

6.链判断运算符 ES2020引入?.

1)const firstName = message?.body?.user?.firstName || ‘default’;
2)等号右边的对象如果是null或undefined,就返回undefined,不在往下计算
3)三种用法:
a.obj?.prop //对象属性
b.obj?.[prop] //对象属性
c.func?.(…args)//函数或对象方法的调用
4)右侧不能是十进制数,不然?.不在被看成一个完整的运算符,小数点.会和后面的数字结合成小数,将变成一个三目运算符

7.Null判断运算符(??)

1)ES2020 引入了一个新的 Null 判断运算符??。它的行为类似||,但是只有运算符左侧的值为null或undefined时,才会返回右侧的值。 (0和false不生效)

const headerText = response.settings.headerText ?? 'Hello, world!';

  • 个人Github,欢迎star^_^
  • ES6总结系列参考自阮一峰《ECMAScript6入门》