对象的扩展和新增方法
对象的简写
- 对象属性简写
let a = 'hello';
let b = { a }; // 相当于{ a: a }
function func(){
let c = 'world'
return { c }; // 相当于 { c: c }
}
console.log(b, func()); // {a: 'hello'} {c: 'world'}
- 对象方法简写
let obj = {
func() {}
}
// 等同于
let obj = {
func: function() {}
}
注意:简写方法不能用作构造函数。
let obj = {
i: 0,
Func() {
console.log(this)
}
}
console.log(obj.Func()); // {i: 0, Func: ƒ}
let func = new obj.Func(); // Uncaught TypeError: obj.Func is not a constructor
属性名
如果对象的属性名是一个变量,需要注意这个变量的类型。
// 变量是数值时
let key = 1;
let obj = {
[key]: 'hello'
}
console.log(obj, typeof Object.keys(obj)[0]); // {1: 'hello'} 'string'
// 变量是Symbol时
let key = Symbol(1);
let obj = {
[key]: 'hello'
}
console.log(obj, typeof Object.keys(obj)[0], obj[key]); // {Symbol(1): 'hello'} 'undefined' 'hello'
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(1)]
// 变量是对象时
let key = {};
let obj = {
[key]: 'hello'
}
console.log(obj); // {[object Object]: 'hello'}
// 变量是数组时
let key = [];
let obj = {
[key]: 'hello'
}
console.log(obj); // {"": 'hello'}
// 变量是布尔值时
let key = true;
let obj = {
[key]: 'hello'
}
console.log(obj, typeof Object.keys(obj)[0]); // {true: 'hello'} 'string'
// 变量是BigInt时
let key = 123n;
let obj = {
[key]: 'hello'
}
console.log(obj, typeof Object.keys(obj)[0]); // {123: 'hello'} 'string'
对象属性的遍历
for ... in可以遍历对象所有可枚举的属性,包括对象本身和对象继承来的属性。Obhect.keys(obj)返回对象自身所有可枚举的属性名Object.getOwnPropertyNames(obj)返回一个数组,包含对象自身所有属性,包括不可枚举的属性,但不包含Symbol属性Object.getOwnPropertySymbols(obj)返回一个数组,包含对象自身所有Symbolg属性,包括不可枚举的Symbol属性Reflect.ownKeys(obj)返回一个数组,包含对象自身所有属性(包含不可枚举的),不管是不是Symbol属性,但不包含继承的。
示例如下:
function Father(name, age) {
this.name = name;
this.age = age;
}
Father.prototype = {
gender: 'male'
}
function Son(name, age) {
Father.call(this, name, age)
}
Son.prototype = Object.create(Father.prototype);
Son.prototype.constructor = Son;
let father = new Father('老明', '38');
Object.defineProperty(father, 'job', {// 此时father对象有两个枚举属性namge,age,一个不可枚举属性job,一个原型上的属性gender
value: 'CEO',
enumerable: false
})
let son = new Son('小明', 12); // son自身有name,age,Symbol(1)三个可枚举属性
son[Symbol(1)] = 'symbol 1';
Object.defineProperty(son, 'job', {
value: '小学生',
enumerable: false
});
Object.defineProperty(son, Symbol(2), {// son有两个不可枚举属性job,Symbol(2)
value: 'symbol 2',
enumerable: false
})
// for in 会输出继承来的可枚举属性
for(key in son) {
console.log(key); // 分别输出name age constructor gender
}
// Object.keys()输出自身可枚举属性
console.log(Object.keys(son)); // ['name', 'age']
// Object.getOwnPropertyNames输出自身可枚举和不可枚举的非Symbol类型属性
console.log(Object.getOwnPropertyNames(son)); // ['name', 'age', 'job']
// Object.getOwnPropertySymbols()输出自身可枚举和不可枚举的Symbol类型属性
console.log(Object.getOwnPropertySymbols(son)); // [Symbol(1), Symbol(2)]
// Reflect.ownKeys()输出自身所有属性
console.log(Reflect.ownKeys(son)); // ['name', 'age', 'job', Symbol(1), Symbol(2)]
Object.is()
Object.is()用来比较两个值是否严格相等,与严格比较运算符===的行为基本一致。
有两个不同点:+0不等于-0;NaN等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign()
Object.assign()用于合并对象,接收N个参数,第一个参数为目标对象,剩余参数为源对象,源对象合并到目标对象,注意,合并的是源对象自身可枚举的属性,同时需注意浅拷贝问题。
let obj = {
a: 1,
}
let obj2 = {
b: 2
}
Object.defineProperty(obj2, 'c', {
enumerable: false,
value: 3
})
console.log(Reflect.ownKeys({...obj, ...obj2})); // ['a', 'b']
console.log(Reflect.ownKeys(Object.assign(obj, obj2))); // ['a', 'b']
console.log(obj); // {a: 1, b: 2}
// 可以看出Object.assign和解构赋值的方式合并没多大差别。
// 需要注意,如果合并的源变量不是对象时,如果是字符串,会对字符串做解构赋值,如果是数值或布尔值,不生效。
let obj = {
a: 1,
}
let obj2 = 'abc';
let obj3 = 100;
let obj4 = true;
console.log({...obj, ...obj2, ...obj3, ...obj4}); // {0: 'a', 1: 'b', 2: 'c', a: 1}
Object.assign(obj, obj2, obj3, obj4);
console.log(obj); // {0: 'a', 1: 'b', 2: 'c', a: 1}
Object.setProtytypeOf(), Object.getPrototypeOf()
用来处理__proto__属性。之前我们做原型链处理可能会使用这个属性来绑定原型。但现在我们用这两个Object方法来处理。
const obj = {
hello: 'world'
}
function Person(){}
Person.prototype = {
abc:'abc'
}
obj.__proto__ = Person.prototype;
console.log(obj.abc); // 'abc'
现在我们改成:
const obj = {
hello: 'world'
}
function Person(){}
Person.prototype = {
abc:'abc'
}
Object.setPrototypeOf(obj, Person.prototype);
console.log(obj.abc); // 'abc'
console.log(Object.getPrototypeOf(obj)); // {abc: 'abc'}
Object.keys(), Object.values(), Object.entries()
都是返回数组。和数组的keys(),values(),entries()方法区分一下,数组的是返回一个迭代器对象。
Object.fromEntries()
Object.entries()的逆操作。将一个键值对数组转成对象。
// 比如我们可以将一个map对象转成普通对象
const map = new Map();
map.set('a', 1);
map.set('b', 2);
console.log(Object.fromEntries(map)); // {a: 1, b: 2}