ES6篇(10)--对象的新增方法


(1)Object.is()
ES5比较两个值是否相等,只有两个运算符:
相等运算符(==),缺点:自动转换数据类型
严格相等运算符(===),缺点NaN不等于自身,+0等于-0

ES6提出同值相等算法,用来解决这个问题--Object.is
用来比较两个值是否严格相等,它与===的行为一致,且+0不等于-0,NaN等于自身

(2)Object.assign()
该方法用于对象的合并,将源对象的所有可枚举属性复制到目标对象;
该方法的第一个参数是目标对象,后面的参数都是源对象;
例子:
const target = { a: 1 };

const source1 = { b: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
说明:1.如果目标对象与源对象有同名属性(或多个源对象有同名属性),则后面的属性
会覆盖前面的属性。
2.如果只有一个参数,该参数是对象,则Object.assign会直接返回该参数
如果该参数不是对象,则会先转成对象,然后返回;
由于undefined和null无法转成对象,所以如果它们做参数,会报错。

3.如果非对象参数出现在源对象的位置(即非首参数),那么这些参数都会转成对象,
如果无法转成对象则跳过(这意味着,如果undefined和null不在首参数,就不会报错。)
(字符串会转成数组形式,拷贝如目标对象,数值,布尔值等拷贝入目标对象不会有效果)
4.Object.assign只拷贝源对象的自身属性,不拷贝继承属性,也不拷贝不可枚举的属性;
但是属性名为Symbol值的属性,会被拷贝

注意点:
1.Object.assign方法是浅拷贝,如果源对象的某个属性的值是对象,则目标对象拷贝得到
的是这个对象的引用,这个对象的任何变化,都会反映到目标对象上。
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

2.同名属性的替换
对于嵌套的对象,遇到同名属性,Object.assign的处理方法是替换,而不是添加
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

3.数组的处理
Object.asign把数组视为对象处理,属性名为下标1,2,3...
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]

4.取值函数的处理
Object.asign只能进行值的复制,如果要复制取值函数,则先求值后复制。
const source = {
  get foo() { return 1 }
};
const target = {};

Object.assign(target, source)
// { foo: 1 }

常见用途:
1.为对象添加属性
class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}

2.为对象添加方法
Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});

3.克隆对象
function clone(origin) {
  return Object.assign({}, origin);
}

4.合并多个对象
const merge =
  (target, ...sources) => Object.assign(target, ...sources);
5.为属性指定默认值


(3)Object.getOwnPropertyDescriptors()
ES5的Object.getOwnPropertyDescriptor()方法--返回某个对象属性的描述对象
ES2017的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 } }

该方法引入的目的
1.主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题
(Object.assign方法总是拷贝一个属性的值,而不会拷贝它背后的复制方法或取值方法)
使用Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以实现正确拷贝。
例子:
const source = {
  set foo(value) {
    console.log(value);
  }
};

const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')
// { get: undefined,
//   set: [Function: set foo],
//   enumerable: true,
//   configurable: true }
上面的代码中,两个对象合并的逻辑可以写成一个函数
const shallowMerge = (target, source) => Object.defineProperties(
  target,
  Object.getOwnPropertyDescriptors(source)
);

2.另一个用处,配合Object.create()方法,将对象属性克隆到一个新对象(这属于浅拷贝)
const clone = Object.create(Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj));

// 或者

const shallowClone = (obj) => Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);

3.实现一个对象继承另一个对象
const obj = Object.create(
  prot,
  Object.getOwnPropertyDescriptors({
    foo: 123,
  })
);

4.实现Mixin(混入)模式(※没看懂)

(4)__pro__属性,Object.setPrototypeof(),Object.getPrototypeof()
1.关于__pro__属性
该属性用来读取或设置当前对象的prototype对象,只有浏览器必须部署这个属性,其他
运行环境不一定需要部署,所以最好不要使用这个属性,而是使用Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替。

2.关于Object.setPrototypeof()
该方法用来设置一个对象的prototype对象,返回参数对象本身--ES6正式推荐的设置原型
对象的方法

// 格式
Object.setPrototypeOf(object, prototype)

// 用法
const o = Object.setPrototypeOf({}, null);

例子:
let proto = {};
let obj = { x: 10 };
Object.setPrototypeOf(obj, proto);

proto.y = 20;
proto.z = 40;

obj.x // 10
obj.y // 20
obj.z // 40

以上代码将proto对象设置为obj对象的原型,所以从obj对象可以读取proto对象的属性。

注意:如果第一个参数不是对象,会自动会转为对象,但是由于返回的还是第一个参数,所以
这个操作不会返回任何效果。
由于undifined和null无法转为对象,所以如果第一个参数是undefined或null,会报错。

3,关于Object.getPrototypeof()
该方法用于读取一个对象的原型对象:Object.getPrototypeOf(obj);
如果参数不是对象,会自动转为对象,如果参数是undefined或null,它们无法转为对象,所以会报错。

4.关于Object.create()
该方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
格式:Object.create(proto[, propertiesObject])

使用注意:
a.Object.create()方法创建的对象时,属性是在原型下面的
【ew Object() 通过构造函数来创建对象, 添加的属性是在自身实例下。】
b.Object.create() 用第二个参数来创建非空对象的属性描述符默认是为false的,而构造函数或字面量方法创建的对象属性的描述符默认为true。
例子:
// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
o = Object.create({}, { p: { value: 42 } })

// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
o.p = 24
o.p
//42

o.q = 12
for (var prop in o) {
   console.log(prop)
}
//"q"

delete o.p
//false

3.创建空对象时不同
用构造函数或对象字面量方法创建空对象时,对象时有原型属性的,即有_proto_;
当用Object.create()方法创建空对象时,对象是没有原型属性的。
参考链接

(5)Object.keys(),Object.values(),Object.entries() 

1.关于Object.keys()
ES5引入Object.keys方法,返回一个数组,成员是参数对象自身
(不含继承的)所有可遍历属性的键名。
2.关于Object.values() 
ES2017引入,方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
返回数组的成员顺序,与本章的《属性的遍历》部分介绍的排列规则一致。
如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组。

注:1.Object.values只返回对象自身的可遍历属性。
2.Object.values会过滤属性名
3.symbol 值的属性。
4.如果参数不是对象,Object.values会先将其转化为对象,如果参数
是布尔值或数值,会返回空数组

3.关于Object.entries()
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

除了返回值不一样,该方法的行为与Object.values基本一致。

用途:1.遍历对象属性
2.将对象转为真正的Map解构
const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
map // Map { foo: "bar", baz: 42 }

(6)Object.fromEntries()
该方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。

Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }
该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。

// 例一
const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);

Object.fromEntries(entries)
// { foo: "bar", baz: 42 }

// 例二
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(map)
// { foo: true, bar: false }


该方法的一个用处是配合URLSearchParams对象,将查询字符串转为对象。

Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "bar", baz: "qux" }


补充:Object.defineProperty()
该方法会直接在一个对象上定义一个新属性,或修改一个对象的现有属性,并返回这个对象。
如果不指定configurable,writable,enumerable,则这些属性值的默认值为false,如果不指定
value,get,set,则这些属性默认值为undefined

语法: Object.defineProperty(obj, prop, descriptor)
obj: 需要被操作的目标对象
prop: 目标对象需要定义或修改的属性的名称
descriptor: 将被定义或修改的属性的描述符

例子:
var obj = new Object();

Object.defineProperty(obj, 'name', {
    configurable: false,
    writable: true,
    enumerable: true,
    value: '张三'
})

console.log(obj.name)  //张三

Object.defineProperties()
功能:
方法直接在一个对象上定义一个或多个新的属性或修改现有属性,并返回该对象。

语法: Object.defineProperties(obj, props)
obj: 将要被添加属性或修改属性的对象
props: 该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置

例子:
var obj = new Object();
Object.defineProperties(obj, {
    name: {
        value: '张三',
        configurable: false,
        writable: true,
        enumerable: true
    },
    age: {
        value: 18,
        configurable: true
    }
})

console.log(obj.name, obj.age) // 张三, 18

参考链接

阮一峰 Es6 对象的新增方法

猜你喜欢

转载自blog.csdn.net/u012149906/article/details/93086502