3

我正在按照教程在 Javascript 中创建 getter 和 setter,我有这样的代码:

// Create a new User object that accept an object of properties
function User(properties) {
    // Iterate through the properties of the object, and make
    // sure it's properly scoped
    for (var i in properties) { (function(){
        // Create a new getter for the property
        this['get' + i] = function() {
            return properties[i];
        };

        // Create a new setter for the property
        this['set' + i] = function(val) {
            properties[i] = val;
        };
    })(); }
}

// Create a new User object instance and pass in an object of
// properties to seed it with
var user = new User({
    name: 'Bob',
    age: 28
});

// Just note that the name property does not exist, as it's private
// within the property object
console.log(user.name == null);

// However, we are able to access its value using the new getname()
// method, that was dynamically generated
console.log(user.getname());

但是,控制台显示错误,提示用户没有方法 getname。该代码试图动态生成 getter 和 setter 方法,对我来说它看起来不错。有什么想法吗?

4

3 回答 3

15

其他答案是正确的,因为您需要传入i匿名函数,但您也可以使用ES5 Getters 和 Setters执行此操作:

// Create a new User object that accept an object of properties
function User(properties) {
    var self = this; // make sure we can access this inside our anon function
    for (var i in properties) {
        (function(i) {
            Object.defineProperty(self, i, {
                // Create a new getter for the property
                get: function () {
                    return properties[i];
                },
                // Create a new setter for the property
                set: function (val) {
                    properties[i] = val;
                }
            })
        })(i);
    }
}

使用 ES5 getter 和 setter 的好处是现在你可以这样做:

var user = new User({name: 'Bob'});
user.name; // Bob
user.name = 'Dan';
user.name; // Dan

由于它们是函数,它们会修改传入的properties,而不仅仅是对象本身。您不必使用getNor setN,您只需使用.N,这使得使用它看起来更像是访问对象的属性。

然而,这种方法并不是普遍可移植的(需要 IE 9+)。

以下是我在实践中可能会做的事情:

function User(properties) {
    Object.keys(properties).forEach(function (prop) {
        Object.defineProperty(this, prop, {
            // Create a new getter for the property
            get: function () {
                return properties[prop];
            },
            // Create a new setter for the property
            set: function (val) {
                properties[prop] = val;
            }
        })
    }, this);
}

以上摆脱了你的 for 循环。您已经在使用匿名函数,所以不妨充分利用它。

于 2013-07-20T17:53:30.963 回答
2

可能是关闭问题:

function User(properties) {
    // Iterate through the properties of the object, and make
    // sure it's properly scoped
    for (var i in properties) { 
        (function(i){
            // Create a new getter for the property
            this['get' + i] = function() {
                return properties[i];
            };

            // Create a new setter for the property
            this['set' + i] = function(val) {
                properties[i] = val;
            };
        }.call(this, i));
    }
}

此外,正如@Paul 指出的那样,this实际上是指包含在 for 循环中的函数。不是User功能。我通过使用调用并将Userthis 分配给函数来解决这个问题(不需要额外的变量)。

于 2013-07-20T17:34:19.240 回答
1

您的循环内函数正在丢失this, do a var t = this; 外部循环并参考t内部。另外,传递i给你的函数。

function User(properties) {
    var t = this, i;
    for (i in properties) (function (i) {
        t['get' + i] = function () { return properties[i]; };
        t['set' + i] = function (val) { properties[i] = val; };
    }(i));
}
于 2013-07-20T17:34:53.377 回答