2020.04.28(Object.getOwnPropertyDescriptors()、__proto__ 属性,Object.setPrototypeOf(), Object.getPrototypeOf())

Object.getOwnPropertyDescriptors()

ES5 的 Object.getOwnPropertyDescriptor()  方法会返回某个对象属性的描述对象
(descriptor)。ES2017 引入了 Object.getOwnPropertyDescriptors()  方法,返回指定对象
所有自身属性(非继承属性)的描述对象。

1.  const obj = {
2.  foo: 123,
3.  get bar() { return 'abc' }
4.  };
5.
6.  Object.getOwnPropertyDescriptors(obj)
7.  // { foo:
8.  // { value: 123,
9.  // writable: true,
10.  // enumerable: true,
11.  // configurable: true },
12.  // bar:
13.  // { get: [Function: get bar],
14.  // set: undefined,
15.  // enumerable: true,
16.  // configurable: true } }

上面代码中, Object.getOwnPropertyDescriptors()  方法返回一个对象,所有原对象的属性名都
是该对象的属性名,对应的属性值就是该属性的描述对象。
该方法的引入目的,主要是为了解决 Object.assign()  无法正确拷贝 get  属性和 set  属性的问
题。

1.  const source = {
2.  set foo(value) {
3.  console.log(value);
4.  }
5.  };
6.
7.  const target1 = {};
8.  Object.assign(target1, source);
9.
10.  Object.getOwnPropertyDescriptor(target1, 'foo')
11.  // { value: undefined,
12.  // writable: true,
13.  // enumerable: true,
14.  // configurable: true }

上面代码中, source  对象的 foo  属性的值是一个赋值函数, Object.assign  方法将这个属性
拷贝给 target1  对象,结果该属性的值变成了 undefined  。这是因为 Object.assign  方法总
是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。

这时, Object.getOwnPropertyDescriptors()  方法配合 Object.defineProperties()  方法,
就可以实现正确拷贝。

const source = {
2.  set foo(value) {
3.  console.log(value);
4.  }
5.  };
6.
7.  const target2 = {};
8.  Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
9.  Object.getOwnPropertyDescriptor(target2, 'foo')
10.  // { get: undefined,
11.  // set: [Function: set foo],
12.  // enumerable: true,
13.  // configurable: true }

上面代码中,两个对象合并的逻辑可以写成一个函数。

__proto__  属性,Object.setPrototypeOf(),
Object.getPrototypeOf()

JavaScript 语言的对象继承是通过原型链实现的。ES6 提供了更多原型对象的操作方法。

__proto__  属性

__proto__  属性(前后各两个下划线),用来读取或设置当前对象的原型对象(prototype)。目
前,所有浏览器(包括 IE11)都部署了这个属性。

1.  // es5 的写法
2.  const obj = {
3.  method: function() { ... }
4.  };
5.  obj.__proto__ = someOtherObj;
6.
7.  // es6 的写法
8.  var obj = Object.create(someOtherObj);
9.  obj.method = function() { ... };

如果一个对象本身部署了 __proto__  属性,该属性的值就是对象的原型。

1.  Object.getPrototypeOf({ __proto__: null })
2.  // null

Object.setPrototypeOf()

Object.setPrototypeOf  方法的作用与 __proto__  相同,用来设置一个对象的原型对象
(prototype),返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。

1.  // 格式
2.  Object.setPrototypeOf(object, prototype)
3.
4.  // 用法
5.  const o = Object.setPrototypeOf({}, null);

下面是一个例子。

1.  let proto = {};
2.  let obj = { x: 10 };
3.  Object.setPrototypeOf(obj, proto);
4.
5.  proto.y = 20;
6.  proto.z = 40;
7.
8.  obj.x // 10
9.  obj.y // 20
10.  obj.z // 40

上面代码将 proto  对象设为 obj  对象的原型,所以从 obj  对象可以读取 proto  对象的属性。
如果第一个参数不是对象,会自动转为对象。但是由于返回的还是第一个参数,所以这个操作不会产生
任何效果。

由于 undefined  和 null  无法转为对象,所以如果第一个参数是 undefined  或 null  ,就会
报错。

1.  Object.setPrototypeOf(undefined, {})
2.  // TypeError: Object.setPrototypeOf called on null or undefined
3.
4.  Object.setPrototypeOf(null, {})
5.  // TypeError: Object.setPrototypeOf called on null or undefined

Object.getPrototypeOf()

该方法与 Object.setPrototypeOf  方法配套,用于读取一个对象的原型对象。

1.  Object.getPrototypeOf(obj);

 

2021-04-28  10:50:20

posted @ 2021-04-28 10:53  铁打的代码流水的bug  阅读(134)  评论(0)    收藏  举报