简体   繁体   English

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

[英]“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: 在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;
            };
        })();
    }
}

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". 运行上面的代码会抛出此错误“user.getname不是函数”。

What is the correct way of generating the dynamic functions for each object instantiated? 为实例化的每个对象生成动态函数的正确方法是什么?

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 查看勘误表: http//www.apress.com/9781590597279

Inside the anonymous function, this is the global window . 在匿名函数内部, this是全局window

You could make it work by adding .call(this, i) after it. 您可以通过在它之后添加.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);
    }
} 

The this in the inner self-executing function is not the same as the this in the outer User function. this在内部自动执行的功能是不一样的在外部的此User功能。 As you noticed, it refers to the global window . 正如您所注意到的,它指的是全局window

The problem is fixed if you slightly modify the code by adding a variable that refers to the outer this . 如果稍有通过添加是指外的可变修改代码的问题得到解决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() { /* ... */ }; 
  }
}

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. 另一个选择是不要在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;
       };
    })(); }
}

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

You can always force another this for any function call, using the apply method. 您始终可以使用apply方法为任何函数调用强制执行this

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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