在Javascript中创建getter和setter

时间:2013-07-20 17:30:05

标签: javascript

我正在按照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方法,对我来说看起来不错。有什么想法吗?

3 个答案:

答案 0 :(得分:12)

其他答案是正确的,因为您需要将i传递给您的匿名函数,但您也可以使用ES5 Getters and 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,而不仅仅是对象本身。您不必再使用getNsetN,只需使用.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循环。你已经在使用匿名函数,所以不妨充分利用它。

答案 1 :(得分: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功能。我通过使用调用并将User指定给函数来修复它(不需要额外的变量)。

答案 2 :(得分:1)

您的循环功能正在丢失this,执行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));
}