返回列表 回复 发帖

[JavaScript] ES6中对象新增方法

本帖最后由 累成狗 于 2017-7-31 15:39 编辑

Object.is()

在JavaScript中常常喜欢使用==或者===来比较两个值,许多开发者更趋向于使用===,从而避免在比较时触发强制类型转换的行为。但事实上,即使使用===来给两个值做比较也并不完全准确。比如,在JavaScript中+0和-0表示为两个完全不同的实体,而如果使用===进行比较,得到的结果是true;而对于NaN === NaN的返回值则是false,此时需要使用isNaN()方法才能检测NaN。

在ES6中引入了Object.is()方法来弥补===不准确运算。这个方法接受两个参数,如果这两个参数类型相同且具有相同的值,则返回true:
  1. console.log(+0 == -0);            // => true
  2. console.log(+0 === -0);           // => true
  3. console.log(Object.is(+0, -0));   // => false

  4. console.log(NaN == NaN);          // => false
  5. console.log(NaN === NaN);         // => false
  6. console.log(Object.is(NaN, NaN)); // => true

  7. console.log(5 == 5);              // => true
  8. console.log(5 == '5');            // => true
  9. console.log(5 === 5);             // => true
  10. console.log(5 === '5');           // => false
  11. console.log(Object.is(5, 5));     // => true
  12. console.log(Object.is(5,'5'));    // => false
复制代码
Object.assign()

在ES5或以下的一些版本,一个对象从另一个对象中接收属性和方法(类似复制对象)。在很多JavaScript库都有一个类似下面的mixin()函数:
  1. function mixin(receiver, supplier) {
  2.     Object.keys(supplier).forEach(function(key){
  3.         receiver[key] = supplier[key];
  4.     });
  5.     return receiver;
  6. }
复制代码
mixin()函数遍历supplier对象的自有属性,并将其拷贝到receiver。这就使得receiver没有通过继承就获得了新的行为。例如:
  1. function EventTarget() {
  2.     // ...
  3. }

  4. EventTarget.prototype = {
  5.     constructor: EventTarget,
  6.     emit: function () {
  7.         // ...
  8.     },
  9.     on: function () {
  10.         // ...
  11.     }
  12. }

  13. var myObject = {};

  14. mixin(myObject, EventTarget.prototype);

  15. myObject.emit('somethingChanged');
复制代码
在这个例子中,myObject从EventTarget.prototype接收了新的行为。

为此在ES6中添加了Object.assign(),它和mixin()的行为一样。但不同之处在于,mixin()使用赋值运算符=来拷贝,它不能拷贝访问属性accessor properties到接受者作为访问属性。Object.assign()是可以做到这点的。

我们可以使用Object.assign()重写上面的mixin()函数:
  1. function EventTarget() {
  2.     // ...
  3. }

  4. EventTarget.prototype = {
  5.     constructor: EventTarget,
  6.     emit: function () {
  7.         // ...
  8.     },
  9.     on: function () {
  10.         // ...
  11.     }
  12. }

  13. var myObject = {}

  14. Object.assign(myObject, EventTarget.prototype);

  15. myObject.emit('somethingChanged');
复制代码
Object.assign()可以接受任意多个提供属性的对象,接收者则按顺序从提供者接收属性,这可能会导致第二个提供者会覆盖第一个提供者提供给接收者的属性。

Object.setPrototypeOf()

正常情况下,无论是通过构造函数还是Object.create()方法创建对象,其原型是在对象被创建时指定的。而在JavaScript中,原型是JavaScript继承时的基础。在ES5中添加了Object.getPrototypeOf()方法来检索任何给定对象的原型。但在ES6中提供了一个相反的操作方法Object.setPrototypeOf(),用来改变任何给定对象的原型。

在ES6之前,是无法在对象创建后来改变其原型,但是ES6的Object.setPrototypeOf()打破了这一情况。Object.setPrototypeOf()接收两个参数,第一个参数为要改变原型的对象,第二个参数为被设置为第一个对象原型的对象。
  1. let person = {
  2.     getGreeting() {
  3.         return "Hello";
  4.     }
  5. };

  6. let dog = {
  7.     getGreeting() {
  8.         return "Woof";
  9.     }
  10. };

  11. // 以 person 对象为原型
  12. let friend = Object.create(person);
  13. console.log(friend.getGreeting());                      //  => "Hello"
  14. console.log(Object.getPrototypeOf(friend) === person);  //  => true

  15. // 将原型设置为dog
  16. Object.setPrototypeOf(friend, dog);
  17. console.log(friend.getGreeting());                      //  => "Woof"
  18. console.log(Object.getPrototypeOf(friend) === dog);     //  => true
复制代码
Object.keys()

ES5 引入了Object.keys()方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
  1. var obj = {
  2.     foo: 'bar',
  3.     baz: 42
  4. };
  5. Object.keys(obj); // => ["foo", "baz"]
复制代码
Object.values()

Object.values()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值
  1. var obj = {
  2.     foo: 'bar',
  3.     baz: 42
  4. };
  5. Object.values(obj);  // => ["bar", 42]
复制代码
返回数组的顺序:
  1. var obj = {
  2.     100: 'a',
  3.     2: 'b',
  4.     7: 'c'
  5. };
  6. Object.values(obj); // => ["b", "c", "a"]
复制代码
上面代码中,属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是b、c、a。

Object.values()只返回对象自身的可遍历属性。
  1. var obj = Object.create({}, {p: {value: 42}});
  2. Object.values(obj); // => []
复制代码
上面代码中,Object.create()方法的第二个参数添加的对象属性(属性p),如果不显式声明,默认是不可遍历的,因为p是继承的属性,而不是对象自身的属性。Object.values()不会返回这个属性。

Object.values()会过滤属性名为 Symbol 值的属性。
  1. Object.values({ [Symbol()]: 123, foo: 'abc' });    // => ['abc']
复制代码
如果Object.values()方法的参数是一个字符串,会返回各个字符组成的一个数组。
  1. Object.values('foo');  // => ['f', 'o', 'o']
复制代码
如果参数不是对象,Object.values()会先将其转为对象。由于数值和布尔值的包装对象,都不会为实例添加非继承的属性。所以,Object.values()会返回空数组。
  1. Object.values(42);    // => []
  2. Object.values(true);  // => []
复制代码
Object.entries()

Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
  1. var obj = {
  2.     foo: 'bar',
  3.     baz: 42
  4. };
  5. Object.entries(obj);  // => [ ["foo", "bar"], ["baz", 42] ]
复制代码
返回列表