javascript - 为什么 .assign 对象合并中的 setter/getter 定义不起作用?

标签 javascript

我正在尝试在我的 JS 应用程序中实现一种继承。 这是我所拥有的:

function FooObject(param1, param2) {
   this._param1= param1;
   this._param2= param2;
}

Object.defineProperties(FooObject.prototype, {
    param1:
    {
        get: function () { return this._param1; },

        set: function (val) { this._param1= val; }
    }
});

上面是一个“基类”,好吗?

然后我定义了另一个对象,它通过合并扩展了 FooObject 并添加了更多属性:

  function FooObjectA(param1, param2, param3, param4) {
    FooObject.call(this, param1, someVal);
    this._param2= param2;
    this._param3= param3;
    this._param4= param4;
  }

 FooObjectA.prototype = Object.assign(Object.create(FooObject.prototype),
 {
     constructor: FooObjectA,

    param2:
    {
        get: function () { return this._param2; },

        set: function (val) { this._param2= val; }
    },

   param3:
    {
        get: function () { return this._param3; },

        set: function (val) { this._param3 = val; }
    }

});

现在,如果我尝试获取 param3,例如:

  var fooInstance = new FooObjectA();
  
  var p = fooInstance .param3;

然后 p 不保存 _param3 的值,而是引用 getter 方法。

然后我尝试了这个方法:

  Object.defineProperties(FooObjectA.prototype, {
  {
   
    param2:
    {
        get: function () { return this._param2; },

        set: function (val) { this._param2= val; }
    },

   param3:
    {
        get: function () { return this._param3; },

        set: function (val) { this._param3 = val; }
    }

});

现在它从 getter 返回值 ok。我是 JavaScript 的新手,想了解为什么当我将 getters/setters 放入 .assign..create... 时它不起作用,因为从逻辑上讲我看不出为什么这些 getters 没有与原型(prototype)合并FooObject.

最佳答案

Object.assign 读取属性的(调用 getter)并将该值作为简单数据属性存储在目标对象上。

如果您想复制 getter/setter 定义,您需要实现自己的函数来检查属性描述符 (Object.getOwnPropertyDescriptor(obj, "propName")) 并处理创建目标上的 getter/setter 属性。

then p doesn't hold the value of _param3 but reference to the getter method.

那是一个单独的问题。您正在将一个对象传递给 Object.assign,并希望它按照 Object.defineProperties 的方式进行解释:

FooObjectA.prototype = smartAssign(Object.create(FooObject.prototype), {
    constructor: FooObjectA,
    param2: {
        get: function() {
            return this._param2;
        },
        set: function(val) {
            this._param2 = val;
        }
    },
    param3: {
        get: function() {
            return this._param3;
        },
        set: function(val) {
            this._param3 = val;
        }
    }
});

如果你想使用那种格式,你需要调用Object.defineProperties来解释它:

FooObjectA.prototype = smartAssign(Object.defineProperties(Object.create(FooObject.prototype), {
// --------------------------------^
    constructor: FooObjectA,
    param2: {
        get: function() {
            return this._param2;
        },
        set: function(val) {
            this._param2 = val;
        }
    },
    param3: {
        get: function() {
            return this._param3;
        },
        set: function(val) {
            this._param3 = val;
        }
    }
})); // <=== Added )

这是执行此操作的函数(使用 ES5 语法)的快速草图;您很可能需要测试并强化它:

var hasOwn = function(obj, prop) { // Paranoia, in case an object overrides it
    return Object.prototype.hasOwnProperty.call(obj, prop);
};
function smartAssign(target) {
    var n, source, key;
    for (n = 1; n < arguments.length; ++n) {
        source = arguments[n];
        for (key in source) {
            if (hasOwn(source, key)) {
                Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
            }
        }
    }
    return target;
}

使用它并修复了另一个问题的实例:

var hasOwn = function(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
};
function smartAssign(target) {
    var n, source, key;
    for (n = 1; n < arguments.length; ++n) {
        source = arguments[n];
        for (key in source) {
            if (hasOwn(source, key)) {
                Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
            }
        }
    }
    return target;
}

function FooObject(param1, param2) {
    this._param1 = param1;
    this._param2 = param2;
}

Object.defineProperties(FooObject.prototype, {
    param1: {
        get: function() {
            return this._param1;
        },
        set: function(val) {
            this._param1 = val;
        }
    }
});

function FooObjectA(param1, param2, param3, param4) {
    FooObject.call(this, param1, 42);
    this._param2 = param2;
    this._param3 = param3;
    this._param4 = param4;
}

FooObjectA.prototype = smartAssign(Object.defineProperties(Object.create(FooObject.prototype), {
    constructor: FooObjectA,
    param2: {
        get: function() {
            return this._param2;
        },
        set: function(val) {
            this._param2 = val;
        }
    },
    param3: {
        get: function() {
            return this._param3;
        },
        set: function(val) {
            this._param3 = val;
        }
    }
}));

var fooInstance = new FooObjectA("p1", "p2", "p3", "p4");
console.log(fooInstance.param1);
console.log(fooInstance.param3);

关于javascript - 为什么 .assign 对象合并中的 setter/getter 定义不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50270256/

相关文章:

javascript - 如何使用正则表达式查找对象成员名称

javascript - 如何使 div 可拖动且可编辑 ="true"?

javascript - 当鼠标快速移动时,在 JQUERY 中自定义拖动 div 无法正常工作

javascript - 谷歌图表错误 :Cannot read property 'length' of undefined; Debugging error in Google Charts

javascript - 将每三个 div 包装为一个

javascript - Angular UI Router 在使用 grunt 构建后不使用模板缓存

javascript - 在 Eclipse 中访问 GWT 生成的 javascript 源

javascript - 映射对象数组,然后映射这些对象中的另一个数组并消除重复项

javascript - 订阅大收藏

javascript - transitionend 使用 if 语句触发 +1 事件