1

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

5 Answers 5

3

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); }
}
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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]

Comments

0

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;
        };
    })(); }
}

Comments

0

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.

3 Comments

What about the "this" inside those anonymous functions inside the loop? They have to refer to the correct this. You have to set a reference inside the user function. Or you can bind the anonymous functions with the current this ;)
The function it being called with the User this when he do .call(this, i). Those anonymous functions inside the loop share the same this because it was explicit given.
I mixed up with @David Hedlund's code. That's the fine way to do it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.