- 属性简写
- 方法简写
- 返回值简写
var a = 'a'
const o = {
a,
method() {
var x = 1
return {x}
}
};
let propKey = 'foo';
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
注意,如果属性名表达式是对象,默认情况下会自动将对象转为字符串[object Object]
const keyA = {a: 1};
const keyB = {b: 2};
const myObject = {
[keyA]: 'valueA',
[keyB]: 'valueB'
};
myObject // Object {[object Object]: "valueB"}
- 正常函数:fn.name
- bind函数:bound + fn.name
- Function构造函数:anonymous
- 对象的getter函数和getter函数:Object.getOwnPropertyDescriptor(obj, 'foo').get.name
- 对象属性名为Symbol的函数:Symbol 值的描述
// 1.正常函数:fn.name
(function a(){}).name // "a"
// 2.bind函数:bound + fn.name
(function a(){}).bind().name // "bound a"
// 3.Function构造函数:anonymous
(new Function()).name // "anonymous"
// 4.对象的getter函数和getter函数:Object.getOwnPropertyDescriptor(obj, 'foo').get.name
const obj = {
get foo() {},
set foo(x) {}
};
obj.foo.name // TypeError: Cannot read property 'name' of undefined
const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
descriptor.get.name // "get foo"
descriptor.set.name // "set foo"
// 5.对象属性名为Symbol的函数:Symbol 值的描述
const key1 = Symbol('description');
const key2 = Symbol();
let obj = {
[key1]() {},
[key2]() {},
};
obj[key1].name // "[description]"
obj[key2].name // ""
通过Object.getOwnPropertyDescriptor(obj, 属性)可以获取该对象属性的描述对象。
描述对象中有 enumerable
属性,称为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性。
有四个操作会忽略enumerable为false的属性( ES6 规定,所有 Class 的原型的方法都是不可枚举的。)
- for...in循环:遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
- Object.keys():返回对象自身的所有可枚举的属性的键名
- JSON.stringify():只串行化对象自身的可枚举的属性
- Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性
ES6 一共有 5 种方法可以遍历对象的属性。
- for...in:遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
- Object.keys(obj):返回数组,包括对象自身的所有可枚举的属性的键名(不含 Symbol 属性)
- Object.getOwnPropertyNames(obj):返回数组,包含对象自身的所有属性的键名(不含 Symbol 属性)
- Object.getOwnPropertySymbols(obj):返回数组,包含对象自身的所有 Symbol 属性的键名
- Reflect.ownKeys(obj):返回数组,包含对象自身的所有键名(包含 Symbol 属性)
规律: Reflect.ownKeys > Object.getOwnPropertyNames(非Symbol) > Object.keys(非Symbol可枚举) Reflect.ownKeys > Object.getOwnPropertySymbols(仅Symbol)
排序:
- 数值键:数值升序排列
- 字符串:加入时间升序排列
- Symbol键:加入时间升序排列
Reflect.ownKeys({ 10:0, 2:0, b:0, a:0, [Symbol('a')]:0, [Symbol('b')]:0}) //["2", "10", "b", "a", Symbol(a), Symbol(b)]
Reflect.ownKeys({ 10:0, 2:0, a:0, b:0, [Symbol('b')]:0, [Symbol('a')]:0}) //["2", "10", "a", "b", Symbol(b), Symbol(a)]
- this指向函数所在的当前对象
- super指向当前对象的原型对象
const proto = {
x: 'hello',
foo() {
console.log(this.x);
},
};
const obj = {
x: 'world',
foo() {
super.foo();
}
}
Object.setPrototypeOf(obj, proto);
obj.foo() // "world"
克隆一个对象,还拷贝对象原型的属性
// 写法二
const clone2 = Object.assign(
Object.create(Object.getPrototypeOf(obj)),
obj
);
// 写法三
const clone3 = Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
- 解构必须是对象
- 赋值变量必须最后一个参数
- 赋值变量是浅拷贝
- 扩展运算符不能取继承自原型对象的属性,但是解构赋值可以
// 1. 解构必须是对象
let { ...z } = null; // 运行时错误
let { ...z } = undefined; // 运行时错误
// 2. 赋值变量必须最后一个参数
let { ...x, y, z } = someObject; // 句法错误
let { x, ...y, ...z } = someObject; // 句法错误
// 3. 赋值变量是浅拷贝
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2
// 4. 赋值变量不能取继承自原型对象的属性
const o = Object.create({ x: 1, y: 2 });
o.z = 3;
let { x, ...newObj } = o;
let { y, z } = newObj;
x // 1
y // undefined
z // 3
等同于使用Object.assign()方法
- 基本类型会转为对象
- 扩展运算符的参数是对象,如果有取值函数get,这个函数是会执行的
{...1} // {}
{...true} // {}
{...undefined} // {}
{...null} // {}
{...'hello'} //{0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}
var a = {a: 1}
var b = {b: 2}
let ab = { ...a, ...b } // {a: 1, b: 2}
{ ...['a', 'b', 'c'] } // {0: "a", 1: "b", 2: "c"}
// 并不会抛出错误,因为 x 属性只是被定义,但没执行
let aWithXGetter = {
...a,
get x() {
throw new Error('not throw yet');
}
};
// 会抛出错误,因为 x 属性被执行了
let runtimeError = {
...a,
...{
get x() {
throw new Error('throw now');
}
}
};