这是我参与更文挑战的第9天,活动详情查看: 更文挑战
静态方法
Object.assign()
ES6新增
-
用法
合并或混入对象。
const target = { a: 1, b: 2 }; const source1 = { b: 3, c: 4 }; const source2 = { b: 5, c: 6 }; Object.assign(target, source1, source2); 复制代码
先把source1中的属性混入到target中,重复的属性会覆盖。再把下一个参数source2的属性混入到target中,重复的覆盖。最后返回target。
target // { // a: 1, // b: 5, // c: 6 // } 复制代码
-
细节
-
只会拷贝source自身的属性,原型上的不算,并且是可枚举的属性,包括符号属性。
source.hasOwnProperty("b")
和source.propertyIsEnumerable("a")
都要返回true才行。当然符号属性也会被复制,虽然符号属性不能被
for-in
遍历,但是上面两个函数都返回true。 -
会调用target的set和source的get。
-
访问器属性的
get
和set
不会被复制走。 -
如果在调用
Object.assign()
期间,抛出了错误,混入的操作是没有回滚的,可能只复制了一半。 -
浅复制,如果属性是引用类型的,只会复制其引用。
-
枚举的顺序是确定性的,先以升序枚举数值键,再以插入顺序枚举字符串和符号键。
-
原始类型会被包装成对象。
const v1 = "abc"; const v2 = true; const v3 = 10; const v4 = Symbol("foo") const obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 原始类型会被包装,null 和 undefined 会被忽略。 // 注意,只有字符串的包装对象才可能有自身可枚举属性。 console.log(obj); // { "0": "a", "1": "b", "2": "c" } 复制代码
-
-
作用
Object.assign({}, obj1, obj2); 复制代码
在创建新对象时,可以把obj1和obj2的属性复制过去。
Object.assign(oldObj, newObj); 复制代码
可以更新对象中已有属性的值。
{...obj1, ...obj2} 复制代码
可以实现相同的效果。
Object.is()
ES6新增。判断同值相等。
在ES6之前,有些==
操作符也无能为力的事情。
NaN == NaN // false
+0 == -0 // true
复制代码
这是不符合常理的。
Object.is(NaN, NaN); // true
Object.is(+0, -0); // false
复制代码
这样才符合常理。
Object.keys()
传入一个对象,返回一个数组,由对象的可枚举的属性名组成。不包含原型上的属性名,也不包含符号属性名。
const person = {
name: "herb", // 普通属性
[Symbol("age")]: 18, // 符号属性
high: "1.8米" // 不可枚举属性
}
Object.defineProperty(person, "high", { enumerable: false });
person.__proto__.father = "hhhhhh"; // 原型上的属性
复制代码
Object.keys(person);
// ["name"]
复制代码
数组里不包含符号和不可枚举属性。
Object.keys("abcd");
// ["0", "1", "2", "3"]
复制代码
ES6之前传入原始值会报错,现在会把原始类型转换成对象,再处理。
Object.values()
传入一个对象,返回一个数组,由对象的可枚举属性值组成。不包含原型上的属性值,也不包含符号属性值。
Object.values(person);
// ["herb"]
复制代码
Object.values("abc");
// ["a", "b", "c"]
复制代码
参数为原始值会转换成对象处理。
Object.entries()
返回一个二维数组,每一个一维数组都有两个元素,键值对。不包含原型上的键值对,也不包含符号键值对。
Object.entries(person);
// [ ["name", "herb"] ]
复制代码
Object.entries("abc");
// [ ["0", "a"], ["1", "b"], ["2", "c"] ]
复制代码
in操作符
-
for-in
无论属性是在实例上还是原型上,只要可枚举。
for(let prop in person) { console.log(prop); } // name // father 复制代码
遍历对象及其原型上的所有可枚举的属性名,但不包括符号属性。
for(let prop in person) { console.log(person[prop]); } // herb // hhhhhh 复制代码
-
in
无论属性是在实例上还是原型上,不管能不能枚举,只要有,就返回
true
。"name" in person // true "father" in person // true 复制代码
Object.getOwnPropertyNames()
传入一个对象,返回一个数组,由对象上所有属性名(无论是否可枚举)组成,不包括符号属性,不包括原型上的。
Object.getOwnPropertyNames(person);
// ["name", "high"]
复制代码
high
作为不可枚举属性也返回了。
Object.getOwnPropertyNames("abc");
// ["0", "1", "2", "length"]
复制代码
原始值转换成对象。
const obj = {
"31": "d",
"0": "a",
"4": "e",
c: "c",
b: "b"
}
Object.getOwnPropertyNames(obj)
// ["0", "4", "31", "c", "b"]
复制代码
对象内的键名如果有数字的话,会按照数字大小排列,其他的按照先后顺序排列。
Object.getOwnPropertySymbols()
传入一个对象,返回一个数组,由所有自身的符号属性名(无论是否可枚举)组成,不包括原型上的。
const sym = {
[Symbol("s1")]: "s1",
[Symbol.for("s2")]: "s2",
[Symbol.iterator]() {
return {
next() {
return {
value: 1,
done: false
}
}
}
}
}
复制代码
Object.getOwnPropertySymbols(sym);
// [Symbol(s1), Symbol(s2), Symbol(Symbol.iterator)]
复制代码
Object.getPrototypeOf
传入一个对象,返回其隐式原型。
Object.getPrototypeOf({}) === Object.prototype
// true
复制代码
{}
是由Object
创建的,所以{}
的隐式原型指向Object.prototype
。
不建议使用对象上的__porto__
属性来获取隐式原型了。
setPrototypeOf()
传入一个对象A和一个对象B,把对象A的原型改为对象B。
Object.setPrototypeOf(obj, prototype)
复制代码
不建议使用,详见MDN,建议使用Object.create()
。
Object.create()
传入一个对象,创建一个新对象,其隐式原型是传进来的对象。
例子详见MDN
Object.create(null);
let obj = {};
obj.__proto__ = null;
复制代码
传入一个null,创建一个空对象,没有原型,没有任何属性。上面两个写法效果是一样的。
Object.create({}, {
prop: {
value: "hhhh"
}
})
复制代码
如果传入了两个参数,那么创建好的对象和第二个参数,相当于传给Object.defineProperties()
。
相当于创建一个对象的同时,还可以赋值。
function inherit(father, son) {
return son.prototype = Object.create(father.prototype, {
constructor: {
value: son,
writable: true,
configurable: true
}
})
}
复制代码
可以通过这种方式,实现继承,father
是son
的父类。
实例方法
hasOwnProperty()
传入一个参数,判断实例上是否有这个属性,返回一个布尔值。不包括原型上的。
const obj = {};
obj.hasOwnProperty("constructor"); // false
Object.prototype.hasOwnProperty("constructor"); // true
复制代码
isPrototypeOf()
传入一个对象,判断这个对象的原型链上有没有调用这个函数的对象。
const obj = {};
Object.prototype.isPrototypeOf(obj); // true
复制代码
obj
的原型链上肯定有Object.prototype
。
obj.isPrototypeOf(Object.prototype); // false
复制代码
Object.prototype
上面已经没有原型了,自然不可能有obj
。
propertyIsEnumerable()
传入一个参数,判断这个参数在对象中是否可以枚举。
const person = {
name: "herb", // 普通属性
[Symbol.for("age")]: 18, // 符号属性
high: "1.8米" // 不可枚举属性
}
Object.defineProperty(person, "high", { enumerable: false });
复制代码
person.propertyIsEnumerable("name"); // true
person.propertyIsEnumerable(Symbol.for("age")); // true
person.propertyIsEnumerable("high"); // false
复制代码