Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"this" inside an anonymous function?

Inside John Resig's book "Pro Javascript techniques" he describes a way of generating dynamic object methods with the below code:

// 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 problem is when I try instantiating the above object, the dynamic methods are being attached to the window object instead of the object instantiated. It seems like "this" is referring to the window.

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

alert( user.getname() );

Running the above code throws this error "user.getname is not a function".

What is the correct way of generating the dynamic functions for each object instantiated?

like image 771
levi Avatar asked Mar 04 '12 02:03

levi


People also ask

What is this in anonymous function?

An anonymous function is a function that is not stored in a program file, but is associated with a variable whose data type is function_handle . Anonymous functions can accept multiple inputs and return one output. They can contain only a single executable statement.

Can we use this keyword in anonymous function?

Anonymous Function is a function that does not have any name associated with it. Normally we use the function keyword before the function name to define a function in JavaScript, however, in anonymous functions in JavaScript, we use only the function keyword without the function name.

What is this in a function?

The this keyword refers to different objects depending on how it is used: In an object method, this refers to the object. Alone, this refers to the global object. In a function, this refers to the global object. In a function, in strict mode, this is undefined .

What is anonymous function in node JS?

An anonymous function is an unnamed function that can be used as a value. The inner anonymous function takes zero arguments and is used as the return value for an outer function that takes two arguments. The outer function is needed to defeat closure.


3 Answers

Is this code from the book? I have the book, but I haven't read through it.

It's an error in the book. Check the errata: http://www.apress.com/9781590597279

Inside the anonymous function, this is the global window.

You could make it work by adding .call(this, i) after it.

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(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);
    }
} 
like image 69
Rocket Hazmat Avatar answered Nov 04 '22 16:11

Rocket Hazmat


The this in the inner self-executing function is not the same as the this in the outer User function. As you noticed, it refers to the global window.

The problem is fixed if you slightly modify the code by adding a variable that refers to the outer this.

function User(properties) {
  var self = this;
  for (var i in properties) { 
    (function() { 
      self["get" + i] = function() { /* ... */ }; 
      self["set" + i] = function() { /* ... */ }; 
    })();
  }
}

That said, I'm not sure why the anonymous self-executing function is even needed here, so you have the simpler option of just leaving it out entirely, like this:

function User(properties) {
  for (var i in properties) { 
      this["get" + i] = function() { /* ... */ }; 
      this["set" + i] = function() { /* ... */ }; 
  }
}
like image 28
Peter Olson Avatar answered Nov 04 '22 16:11

Peter Olson


Here is how to do it. You need to save the context into another variable. The other option is not to do this inner function that you are doing in the for loop.

// 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 that = this;
   for ( var i in properties ) { (function(){
       // Create a new getter for the property
       that[ "get" + i ] = function() {
          return properties[i];
       };
       // Create a new setter for the property
       that[ "set" + i ] = function(val) {
           properties[i] = val;
       };
    })(); }
}

Option 2:

// 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 ) {
       // 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;
       };
    }
}
like image 45
Nikola Borisov Avatar answered Nov 04 '22 16:11

Nikola Borisov