Object.assign的意外输出

use*_*833 4 javascript object ecmascript-6

所以我有点惊讶:

Object.assign({}, Math)
Run Code Online (Sandbox Code Playgroud)

其中返回了一个空对象.我这样做是为了建立我自己的数学模块,我可以使用自己的自定义功能扩展,所以我认为这样做很方便:

Object.assign({}, Math, { 
  sqrt: <my-sqrt-implementation>, 
  add: <my-add-implementation >,
})
Run Code Online (Sandbox Code Playgroud)

但我很惊讶地发现没有包含数学条目,为什么呢?在我的控制台中,我得到:

Object.assign({}, Math)
> {}
Run Code Online (Sandbox Code Playgroud)

出了什么问题,怎么解决?

Fen*_*ang 5

属性Math不是可枚举的.Object.assign将仅复制可枚举和自己的属性:

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

因此,您应该遵循该建议,并使用Object.getOwnPropertyNames(Math)获取自己的属性名称列表,然后Object.defineProperty()分配它们:

const props = Object.getOwnPropertyNames(Math)
const myMath = {}
props.forEach(prop => {
    Object.defineProperty(myMath, prop, Object.getOwnPropertyDescriptor(Math, prop))
})

myMath.sin(3.14)  // 0.00159265...
Run Code Online (Sandbox Code Playgroud)

当然,Object.create在这里使用原型继承()可能更好.我提供此代码是因为它更贴切地匹配行为Object.assign,即赋值.