javascript - Object.assign() 的糟糕用例 - 简单示例

标签 javascript object prototype

我正在阅读 MDN docsObject.assign() 上遇到一个我不明白的短语:

The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters. For copying property definitions, including their enumerability, into prototypes Object.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead.

特别是这一行:

This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters.

我不太确定提倡反对使用 Object.assign 的好例子是什么。

最佳答案

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 没有复制 getter,它只是获取 getter 的当前值并将其分配给 obj2.example

可以复制 getter,只是不能使用 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

当然,如果 getter 没有设计成在对象之间复制(例如,如果 example 的 getter 显式使用 obj),您可能会得到意想不到的结果结果。

关于javascript - Object.assign() 的糟糕用例 - 简单示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45772178/

相关文章:

javascript - Javascript 中的对象构造函数和返回值

javascript - 向 $resource 原型(prototype)添加一个函数

javascript - Strapi 没有从 Digital Ocean 上托管的现有 MongoDB 加载集合

javascript - Facebook - 获取带有/不带有访问 token 的页面 ID

javascript - 根据精确值重新排序数组

javascript - 如何在 JavaScript 中跟踪字符串变量

javascript - 为什么 JSON.stringify 不序列化原型(prototype)值?

javascript - 那么关于在node.js中请求

javascript - ES 模块和 jsconfig.json : Error [ERR_MODULE_NOT_FOUND]

javascript - 将预先创建的对象(o1,o2,o3 ..)存储在数组中