对象扩展
ES6 一共有 5 种方法可以遍历对象的属性。
(1)for...in
for...in
循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
(2)Object.keys(obj)
Object.keys
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames
返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols
返回一个数组,包含对象自身的所有 Symbol 属性的键名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys
返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
super 关键字
super
指向当前对象的原型对象
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"
Object.is()
它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign()
Object.assign()
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
Object.assign()
方法的第一个参数是目标对象,后面的参数都是源对象。
如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
如果该参数不是对象,则会先转成对象,然后返回。
typeof Object.assign(2) // "object"
上面代码中,v1
、v2
、v3
分别是字符串、布尔值和数值,结果只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略。这是因为只有字符串的包装对象,会产生可枚举属性。
const v1 = 'abc';
const v2 = true;
const v3 = 10;
const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
注意点
-
浅拷贝
源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
const obj1 = {a: {b: 1}}; const obj2 = Object.assign({}, obj1); obj1.a.b = 2; obj2.a.b // 2
-
同名属性的替换
一旦遇到同名属性,
Object.assign()
的处理方法是替换,而不是添加。const target = { a: { b: 'c', d: 'e' } } const source = { a: { b: 'hello' } } Object.assign(target, source) // { a: { b: 'hello' } }
-
数组的处理
Object.assign()
可以用来处理数组,但是会把数组视为对象。Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3]
上面代码中,
Object.assign()
把数组视为属性名为 0、1、2 的对象,因此源数组的 0 号属性4
覆盖了目标数组的 0 号属性1
这里的key
值就是数组的index
-
取值函数的处理
复制函数的返回值
const source = { get foo() { return 1 } }; const target = {}; Object.assign(target, source) // { foo: 1 }
常用点
-
为对象添加属性
class Point { constructor(x, y) { Object.assign(this, {x, y}); }}
-
为对象添加方法
Object.assign(SomeClass.prototype, { someMethod(arg1, arg2) { ··· }, anotherMethod() { ··· }});// 等同于下面的写法SomeClass.prototype.someMethod = function (arg1, arg2) { ···};SomeClass.prototype.anotherMethod = function () { ···};
-
克隆对象
采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。
当克隆对象只有一级时候可以看做深拷贝
function clone(origin) { return Object.assign({}, origin);}
-
合并多个对象
const merge = (target, ...sources) => Object.assign(target, ...sources);
-
为属性指定默认值
const DEFAULTS = { logLevel: 0, outputFormat: 'html'};function processContent(options) { options = Object.assign({}, DEFAULTS, options); console.log(options); // ...}
Object.assign()
方法将DEFAULTS
和options
合并成一个新对象,如果两者有同名属性,则options
的属性值会覆盖DEFAULTS
的属性值。
Object.getOwnPropertyDescriptors()
会返回某个对象属性的描述对象
const obj = { foo: 123, get bar() { return 'abc' }};Object.getOwnPropertyDescriptors(obj)// { foo:// { value: 123,// writable: true,// enumerable: true,// configurable: true },// bar:// { get: [Function: get bar],// set: undefined,// enumerable: true,// configurable: true } }
__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
__proto__
属性,用来读取或设置当前对象的原型对象
// es5 的写法const obj = { method: function() { ... }};obj.__proto__ = someOtherObj;// es6 的写法var obj = Object.create(someOtherObj);obj.method = function() { ... };
Object.setPrototypeOf()
用来设置一个对象的原型对象
let proto = {};let obj = { x: 10 };Object.setPrototypeOf(obj, proto);proto.y = 20;proto.z = 40;obj.x // 10obj.y // 20obj.z // 40
Object.getPrototypeOf()
用于读取一个对象的原型对象。
function Rectangle() { // ...}const rec = new Rectangle();Object.getPrototypeOf(rec) === Rectangle.prototype// trueObject.setPrototypeOf(rec, Object.prototype);Object.getPrototypeOf(rec) === Rectangle.prototype// false
Object.keys(),Object.values(),Object.entries()
Object.keys
方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
var obj = { foo: 'bar', baz: 42 };Object.keys(obj)// ["foo", "baz"]
Object.values
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
const obj = { foo: 'bar', baz: 42 };Object.values(obj)// ["bar", 42]
Object.entries()
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
const obj = { foo: 'bar', baz: 42 };Object.entries(obj)// [ ["foo", "bar"], ["baz", 42] ]