属性的简洁表示法
- 可以只写属性名,不写属性值,return{x, y}相当于return{x:x, y:y}
- 属性方法简写:method(){}
- 例子:Common.js模块输出变量module.export = {fun1, fun2, fun3}
属性的赋值取值(setter/getter)
属性名表达式
- 定义对象属性
let propKey = 'foo';
let obj = {
[propKey]: true,
['a' + 'bc']: 123, //定义属性
['h' + 'ello']() { //定义方法名
return 'hi';
}
};
- 属性名表达式与简洁表示法,不能同时使用,会报错
var foo = 'bar';
var bar = 'abc';
var baz = { [foo] }; //Unexpected token }
var baz = { [foo]: 'abc'}; //正确
方法的name属性
- 返回函数名,
(1)如果使用了取值函数则会在方法名前加上get,存值会加上set
(2)bind方法创造的函数,name属性返回bound加上原函数的名
(3)Function构造函数创造的函数,name属性返回anonymous。
(4)对象的方法是一个 Symbol 值,那么name属性返回的是这个 Symbol 值的描述。
Object.is()
- 比较两个值是否严格相等(与===不同一是+0不等于-0,二是NaN等于自身)
Object.is({}, {}) // false
Object.assign()
- 用于对象合并Object.assign(target, source1, source2); 第一个参数是源对象,后面的均为目标对象
- 同名情况后者覆盖前者
- 如果该参数不是对象,则会先转成对象
- 由于undefined和null无法转成对象,所以如果它们作为参数,就会报错(如果undefined和null不在首参数,就不会报错)
- 不是对象的情况下,只有字符串的包装对象会产生可枚举属性
var v1 = 'abc';
var v2 = true;
var v3 = 10;
var obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
- 只拷贝自身属性,不拷贝继承属性,它们的原始值都在包装对象的内部属性[[PrimitiveValue]]上面,不会被拷贝,属性名为Symbol值的属性,也会被Object.assign拷贝
- 浅拷贝而非深拷贝,只拷贝对象的引用
- Object.assign可以用来处理数组,但是会把数组视为对象 并且后置位数组会覆盖前置位相同的索引项
- 常见用途
(1)为对象添加属性
(2)为对象添加方法
(3)克隆对象
(4)合并多个对象
(5)为属性指定默认值
(6)不会对复杂属性进行类似于解构赋值的简单覆盖
属性的可枚举性
- Object.getOwnPropertyDescriptor获取属性描述对象
- ES2017 引入了Object.getOwnPropertyDescriptors方法,返回指定对象所有自身属性(非继承属性)的描述对象
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
// { 属性描述对象
// value: 123, 值
// writable: true, 可写
// enumerable: true, 可枚举
// configurable: true 描述对象是否可修改
// }
- 会忽略不可枚举属性的操作
(1)for…in
(2)Obiect.keys() 返回可枚举属性键名
(3)JSON.stringify() 对象可枚举属性串化
(4)Object.assign() 拷贝对象可枚举属性
toString和length属性的enumerable都是false
es6,所有Class的原型的方法都是不可枚举的
属性的遍历
- for..in 循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)
- Object.keys(obj) 返回数组,包含对象自身(不含继承,Symbol)所有可枚举属性
- Object.getOwnPropertyNames(obj) 同上但包含不可枚举属性
- Object.getOwnPropertySymbols(obj) 返回一个数组,包含对象自身的所有Symbol属性。
- Reflect.ownKeys(obj) 返回数组,包含自身所有属性
遍历规则:
(1)属性名为数值,按数字排序
(2)字符串,按生成时间排序
(3)Symbol,生成时间排序
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
- proto
(1)用来读取或设置当前对象的prototype对象
(2)使用下面的Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替 - Object.setPrototypeOf()
(1)Object.setPrototypeOf(obj, proto); 第一个参数不是对象,自动转化为对象
(2)undefined和null无法转为对象,所以如果第一个参数是undefined或null,就会报错。 - Object.getPrototypeOf()
(1)读取对象的原型对象
(2)如果参数不是对象,会被自动转为对象
(3)参数是undefined或null,它们无法转为对象,所以会报错
Object.keys(),Object.values(),Object.entries()
- Object.keys()
(1) 返回数组,成员是参数对象自身的所有可遍历属性(enumerable)键名 - Object.values()
(1)键值
(2)会过滤Symbol值属性
var obj = Object.create({}, {p: {value: 42}});
Object.values(obj) // []
//Object.create方法的第二个参数添加的对象属性(属性p),如果不显式声明,默认是不可遍历的
(3)如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组
(4)如果参数不是对象,Object.values会先将其转为对象
3. Object.entries()
(1)键值对
for (let [k, v] of Object.entries(obj)) {
console.log(
`${JSON.stringify(k)}: ${JSON.stringify(v)}`
);
}
(2)将对象转为Map解构
Null 传导运算符(?.)
- const firstName = message?.body?.user?.firstName || ‘default’;
- 只要其中一个返回null或undefined,就不再往下运算,而是返回undefined
- “Null 传导运算符”有四种用法。
obj?.prop // 读取对象属性
obj?.[expr] // 同上
func?.(…args) // 函数或对象方法的调用
new C?.(…args) // 构造函数的调用