JS中的属性描述对象 5

2018-05-09  本文已影响0人  诗和远方何你

对象的拷贝

有时,我们需要将一个对象的所有属性,拷贝到另一个对象。ES5没有提供这个方法,必须自己实现。

var extend = function (to, from) {
  for (var property in from) {
    to[property] = from[property];
  }

  return to;
}

extend({}, {
  a: 1
})
// {a: 1}

上面这个方法的问题在于,如果遇到存取器定义的属性,会只拷贝值。

extend({}, {
  get a() { return 1 }
})
// {a: 1}

为了解决这个问题,我们可以通过Object.defineProperty方法来拷贝属性。

var extend = function (to, from) {
  for (var property in from) {
    Object.defineProperty(
      to,
      property,
      Object.getOwnPropertyDescriptor(from, property)
      //读取from上property属性的属性描述对象
    );
  }
  return to;
}

extend({}, { get a(){ return 1 } })
// { get a(){ return 1 } })

这段代码还是有问题,拷贝某些属性时会失效。

extend(document.body.style, {
  backgroundColor: "red"
});

上面代码的目的是,设置document.body.style.backgroundColor属性为red,但是实际上网页的背景色并不会变红。但是,如果用第一种简单拷贝的方法,反而能够达到目的。这提示我们,可以把两种方法结合起来,对于简单属性,就直接拷贝,对于那些通过属性描述对象设置的属性,则使用Object.defineProperty方法拷贝。

var extend = function (to, from) {
  for (var property in from) {
    var descriptor = Object.getOwnPropertyDescriptor(from, property);

    if (descriptor && ( !descriptor.writable
      || !descriptor.configurable
      || !descriptor.enumerable
      || descriptor.get
      || descriptor.set)) {
      Object.defineProperty(to, property, descriptor);
    } else {
      to[property] = from[property];
    }
  }
}

上面的这段代码,可以很好地拷贝对象所有可遍历(enumerable)的属性。

上一篇 下一篇

猜你喜欢

热点阅读