简体   繁体   中英

Dynamically Generated Methods in JavaScript

While searching the web, I've encountered a post that shows why the following example of dynamically generated methods does not work as planned:

// Create a new user object that accepts an object of properties
function User( properties ) {
    // Iterate through the properties of the object, and make sure
    // that it's properly scoped (as discussed previously)
    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;
        };
    })(); }
}

The reason for that is the anonymous function, which uses the "this" keyword is context of the "window", instead of "User".

1) Why does the this keyword in the anonymous function refers to "window instead of "User"?

2) Is there an accepted and common way to create "Dynamically Generated Methods"?

Thanks,

Joel

The reason that this refers to the window object, rather than User , is because this depends on the caller. In this case, the foreach contains an anonymous function that is immediately called. The caller will be considered to be the window object.

The reason it's not working is because the code is poorly written. It would be a simple thing to pass both context and the i -variable to be scoped:

function User( properties ) {
    // Iterate through the properties of the object, and make sure
    // that it's properly scoped (as discussed previously)
    for ( var i in properties ) { (function(x){
        // Create a new getter for the property
        this[ "get" + x ] = function() {
            return properties[x];
        };
        // Create a new setter for the property
        this[ "set" + x ] = function(val) {
            properties[x] = val;
        };
    }).call(this, i); }
}

I did try all your examples, but no one has worked perfectly.

This is the working code:

function User( properties ) {
    // Iterate through the properties of the object, and make sure
    // that it's properly scoped (as discussed previously)

    var that = this;

    for ( var i in properties ) { (function(){
        // Create a new getter for the property

        that[ "get" + i ] = function(i) {
            return function (){
                console.debug(i);
                return properties[i];        
            }

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

var user = new User({
    name: "Bob",
    age: 44
});

console.log(user.getname(), user.getage()) //Bob, 44
user.setname("Antonio");
user.setage(33);
console.log(user.getname(), user.getage()) //Antonio, 33

More explanation to the following link computerone.altervista.org

You need to set a proper reference of the "this" element. You are inside an anonymous scope. As the first line of the function "User" you should declare a variable like

var _this = this;

Then, instead of calling this[ "get" + i], you have to call _this[ "get" + i]

Try:

// Create a new user object that accepts an object of properties
function User( properties ) {
    // Iterate through the properties of the object, and make sure
    // that it's properly scoped (as discussed previously)

    var self = this;

    for ( var i in properties ) { (function(){
        // Create a new getter for the property
        self[ "get" + i ] = function() {
            return properties[i];
        };
        // Create a new setter for the property
        self[ "set" + i ] = function(val) {
            properties[i] = val;
        };
    })(); }
}

The problem there is the missing new operator. If you instance your User without it, the this inside will be window .

This will not work:

var george = User(properties);

This will work:

var george = new User(properties);

This tutorial it's interesting to follow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM