1

我正在尝试通过以下方式在匿名函数中访问对象的成员函数-

  function a()
    {
      this.memb = 10;
    }

    a.prototype.hide_member = function(id){
      alert(id);
    }

    a.prototype.show_member = function(){
      setTimeout('this.hide_member(this.memb)', 2000); //Problem 1
      setTimeout(this.hide_member(this.memb), 2000); //Problem 2
      setTimeout(alert(this.memb), 2000);  //Problem 3
      this.memb++;
    }

    var obj = new a();
    obj.show_member();

在这里,问题 1 -代码是在正确的时间执行给定的,意思是在 2000 毫秒之后,但它在 2000 毫秒之后显示以下错误 -

Uncaught TypeError: Object [object global] has no method 'hide_member'
(anonymous function)

问题 2 -代码正在执行,但在解析代码后立即执行,这意味着不是在 2000 毫秒之后。

问题 3 -与问题 2 相同的问题

我在这里对这三个问题感到困惑。谢谢

4

3 回答 3

4

A couple of things are going on here:

In this code:

setTimeout(this.hide_member(this.memb), 2000);

you're calling this.hide_member immediately, and passing its return value into setTimeout. This is exactly like foo(bar()), where you're calling bar and passing its return value into foo.

You need to pass a function into setTimeout, and then call the member function from within that function. Note that within the function, this will be different, so you have to remember it:

a.prototype.show_member = function(){
  var self = this,
      memb_to_hide = this.memb;
  setTimeout(function() {
      self.hide_member(memb_to_hide);
  }, 2000);
  this.memb++;
}

Note that I also remembered the old value of this.memb to use in the function.

Another way to do that is with ES5's Function#bind, but it requires that the browser's JavaScript engine have that (or that you've loaded an "ES5 shim", as bind is a shimmable feature):

a.prototype.show_member = function(){
  setTimeout(this.hide_member.bind(this, this.memb), 2000);
  this.memb++;
}

Function#bind returns a function that, when called, will call the original function using the value you give in the first argument as this (and then passing on any further arguments). In this case, we didn't have to remember the old value of this.memb because we've already passed the old value into bind.


Side note: You're relying on the horror that is Automatic Semicolon Insertion. I recommend not doing that, and supplying semicolons at the ends of your statements, e.g.:

a.prototype.mumble = function() {
    /*...*/
}; // <=== Note the ;
于 2013-09-25T10:31:45.957 回答
1

代码是在正确的时间执行给定的,意思是在 2000 毫秒之后,但在 2000 毫秒之后显示以下错误

错误是不言自明的:this指的是全局对象而不是a类的实例。为避免这种情况,您必须保存对实例上下文的引用:

a.prototype.show_member = function(){
    var self = this; //self refers to the instance
    setTimeout('self.hide_member(self.memb)', 2000);
    this.memb++;
}

代码正在执行,但它在代码解析后立即执行,这意味着不是在 2000 毫秒之后。

它在解析之后执行(更清楚的是show_member在最后一行调用时执行),因为它是一个函数调用:

setTimeout(this.hide_member(this.memb), 2000);

setTimeout需要一个字符串或一个函数才能正确执行,您在这里所做的是执行该函数并返回一个值(在这种情况下没有,所以它是undefined),它将setTimeout在 2000 毫秒后执行。调用的结果是什么undefined?一个错误。在第三种情况下,问题完全相同。

注意:重要的是要强调传递字符串setTimeout是 eval 的一种形式,应该避免它;您可以改为传递匿名函数:

a.prototype.show_member = function(){
    var self = this; //self refers to the instance
    setTimeout(function() {
        self.hide_member(self.memb); 
    }, 2000);
    this.memb++;
}
于 2013-09-25T10:32:41.217 回答
0

Try this:

a.prototype.show_member = function(){
  var self = this;
  setTimeout('self.hide_member(self.memb)', 2000); //Problem 1
  setTimeout(function() { self.hide_member(self.memb) }, 2000); //Problem 2
  setTimeout(function() { alert(self.memb) }, 2000);  //Problem 3
  this.memb++;
}
于 2013-09-25T10:32:10.863 回答