1

我有这个构造函数对象:

function Bindable(obj) {
    var prop;

    for (prop in obj) {
        this.__defineGetter__(prop, function () {
            return obj[prop];
        });

        this.__defineSetter__(prop, function (val) {
            obj[prop] = val;
        });
    }
}

被称为这样的:

var model = new Bindable({
    name: 'Dave',
    level: 10,
    strength: 5
});

如果 I console.log(model),则输出为:

Bindable { name=5, level=5, strength=5 }

为什么构造函数中的每个属性都分配了相同的值?

4

2 回答 2

2

您正在创建一个闭包,该闭包在 getter/setter 函数执行时进行评估,而不是在定义它们时进行评估。在它们执行时,prop具有在循环执行期间分配的最后一个值。您需要避免在prop. 一种方法是使用IIFE。而不是使用这个参数:

function () {
    return obj[prop];
}

利用

(function(p) {
    return function() {
        return obj[p];
    };
}(prop));
于 2013-06-19T23:06:58.157 回答
1

作为替代方案,这应该适合您。

与@Ted Hopp解释的原理相同

但是现在我们有了一个可重用的函数createGetterSetter,它使用 ECMA5 方法Object.defineProperty来定义getter 和 setter ,正如 @Benjamin Gruenbaum所指出的那样。

它也使用 ECMA5Object.keys而不是for..in您使用的。

我认为这比 Ted 建议的解决方案更整洁(每个人都有自己的偏好)。

我不确定改进空间的唯一部分是var self = this;

Javascript

/*jslint maxerr: 50, indent: 4, browser: true */
/*global console */

(function () {
    "use strict";

    function createGetterSetter(object, map, prop) {
        Object.defineProperty(object, prop, {
            get: function () {
                return map[prop];
            },
            set: function (val) {
                map[prop] = val;
            }
        });
    }

    function Bindable(obj) {
        var self = this;

        Object.keys(obj).forEach(function (prop) {
            createGetterSetter(self, obj, prop);
        });
    }

    var model = new Bindable({
        name: 'Dave',
        level: 10,
        strength: 5
    });

    console.log(model.name, model.level, model.strength);
}());

输出

Dave 10 5

jsfiddle 上

于 2013-06-20T00:36:57.613 回答