2017-08-19 86 views
4

我读上Object.assign()MDN docs和跨一个短语来了,我不明白:可怜的用例 - 简单的例子

的Object.assign()方法仅复制可枚举并拥有从源对象到目标对象的属性。它使用源上的[[Get]]和目标上的[[Set]],所以它会调用getter和setter。因此它分配属性而不是复制或定义新属性。如果合并源包含getter,这可能会使它不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型中,应该使用Object.getOwnPropertyDescriptor()和Object.defineProperty()。

特别是这一行:

这可能使其不适合用于合并新特性为原型,如果合并源包含干将。

我不完全确定什么是一个很好的例子是倡导反对使用Object.assign

回答

5

A getter是用于返回属性值的属性的访问器函数。这是一个getter对象的样子:

var obj = { 
 
    get example() { 
 
     console.log("getter was called"); 
 
     return Math.floor(Math.random() * 100); 
 
    } 
 
}; 
 
console.log(obj.example); 
 
// Note no() ---------^

注意,当我们读到example属性的值,函数获取运行,即使它看起来并不像一个函数呼叫。

MDN文档的那部分内容是,Object.assign调用该getter,它不会在目标对象上创建一个等效的getter。所以:

var obj = { 
 
    get example() { 
 
     console.log("getter was called"); 
 
     return Math.floor(Math.random() * 100); 
 
    } 
 
}; 
 
var obj2 = Object.assign({}, obj); // calls getter 
 
console.log(obj2.example);   // just has a simple value 
 
console.log(obj2.example);   // same value, no call 
 
console.log(obj2.example);   // same value, no call

objexample酒店有一个getter,但obj2example属性只是一个简单的价值属性。 Object.assign没有复制吸气剂,它只是抓住吸气剂的当前值并将其分配给obj2.example

可以副本干将,只是不能与Object.assign

function copyProperties(target, source) { 
 
    Object.getOwnPropertyNames(source).forEach(name => { 
 
     Object.defineProperty(
 
      target, 
 
      name, 
 
      Object.getOwnPropertyDescriptor(source, name) 
 
     ); 
 
    }); 
 
    return target; 
 
} 
 
var obj = { 
 
    get example() { 
 
     console.log("getter was called"); 
 
     return Math.floor(Math.random() * 100); 
 
    } 
 
}; 
 
var obj2 = copyProperties({}, obj); // calls getter 
 
console.log(obj2.example);   // calls getter 
 
console.log(obj2.example);   // calls getter 
 
console.log(obj2.example);   // calls getter

当然,如果吸气不是设计对象之间进行复制(例如,如果example的明确使用obj),你可能会得到意想不到的结果。

+0

这非常有道理,谢谢。但是如果我为'source'对象添加了特定的非枚举属性,并且我正在使用'getOwnPropertyNames'的最后一个示例呢?即使那些我们使用这种方法来获得不可枚举的getter和setter,它也会拿起其他任何非枚举类型(比如'length',如果它是一个数组对象的话)。所以我必须在自定义'copyProperties'方法中手动排除它们,是的? – qarthandso

+0

@qarthandso:我刚刚几乎随意使用了'getOwnPropertyNames',想知道是否有人想复制getter和setter等,他们可能也想复制非枚举属性。 (按照这个逻辑,我可能应该也包含'getOwnPropertySymbols';但它只是一个小例子。)如果你想复制属性,但坚持可枚举的属性,使用'Object.keys',它只给你自己的,可枚举属性。 –