“这个”在一个匿名函数里面?

时间:2012-03-04 02:55:38

标签: javascript anonymous-function

在John Resig的书“Pro Javascript技术”中,他描述了一种使用以下代码生成动态对象方法的方法:

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

问题是当我尝试实例化上述对象时,动态方法被附加到窗口对象而不是实例化的对象。似乎“这个”指的是窗口。

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

运行上面的代码会抛出此错误“user.getname不是函数”。

为实例化的每个对象生成动态函数的正确方法是什么?

4 个答案:

答案 0 :(得分:11)

这本书的代码是?我有这本书,但我还没读完。

这本书中的错误。查看勘误表:http://www.apress.com/9781590597279

在匿名函数中,this是全局window

您可以通过在其后添加.call(this, i)来使其发挥作用。

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

答案 1 :(得分:3)

内部自执行函数中的this与外部User函数中的window不同。如您所见,它指的是全局this

如果您通过添加引用外部function User(properties) { var self = this; for (var i in properties) { (function() { self["get" + i] = function() { /* ... */ }; self["set" + i] = function() { /* ... */ }; })(); } } 的变量稍微修改代码,问题就解决了。

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

那就是说,我不确定为什么这里甚至需要匿名的自动执行功能,所以你可以选择简单地将其完全删除,如下所示:

{{1}}

答案 2 :(得分:1)

以下是如何做到这一点。您需要将上下文保存到另一个变量中。另一个选择是不要执行你在for循环中执行的内部函数。

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

选项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;
       };
    }
}

答案 3 :(得分:1)

您可以使用this方法为任何函数调用强制执行另一个apply

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