繁体   English   中英

从JavaScript计时器调用非全局函数

[英]Invoke a non-global function from a javascript timer

是否有可能以某种方式从计时器调用非全局函数(即类的方法)?

以下示例显示了我想要实现的目标:

function MyClass() {
  var msg = 'no message';

  // shows an alert after some delay
  this.delayedAlert = function(message) {
    msg = message;

    // global function works:
    //window.setTimeout('globalShow("'+message+'")', 1000);
    // this obviously also works:
    //this.show();

    // this doesn't work: *************
    // I'd like to invoke the show() method of this class after some delay
    window.setTimeout('this.show()', 2000);
  };
  this.show = function() {
    alert(msg);
  };
}

$(document).ready(function() {
  $('p').click(function() {
    var c = new MyClass();
    c.delayedAlert('hello');
  });
});

function globalShow(msg) {
   $('#hello').html(msg);
}

您可以在此处找到运行示例: http : //jsbin.com/aqako5

function MyClass() {
  var msg = 'no message';

  // shows an alert after some delay
  this.delayedAlert = function(message) {
    msg = message;

    window.setTimeout($.proxy(this.show, this), 2000);
  };
  this.show = function() {
    alert(msg);
  };
}

请使用setTimeout函数。 字符串称为evaleval类似于goto 即猛禽会抓住你。

实际上发生的是在setTimeout函数内部, this值是默认的this值,即window。 你需要在代理法通过,使得this是你想要的this是。

一个替代图案以正确进行代理this值是:

function MyClass() {
  var msg = 'no message';
  var that = this;

  // shows an alert after some delay
  this.delayedAlert = function(message) {
      msg = message;

      window.setTimeout(function() {
          that.show();
      }, 2000);
    };
    this.show = function() {
        alert(msg);
    };
}

这涉及在单独的变量中“缓存”正确的this值。 您仍然不能直接传递that.show ,因为该函数将在不知道this是什么的情况下被调用。

这会有所帮助。 还可以改善您的课程:如果您的课程未实例化,则可能会引起问题。 如果有人这样叫您的班怎么办:

var myClass = MyClass();

MyClass内部的this现在将成为窗口,从而导致各种问题,并将您的属性添加到全局名称空间。

要解决此问题,您需要确保在调用类函数时,它是使用new运算符完成的。 您需要在MyClass内部检查,如果这不是MyClass的新实例,则必须将其强制为新实例。 在下面的代码中,您可以通过以下两种方式之一调用此方法,并使它们都以相同的方式起作用:

var myClass = MyClass();
// or
var myClass = new MyClass();

将您的班级更改为此:

function MyClass() {
    // if this isn't an instance, make it so:
    if (!(this instanceof MyClass)) {
        return new MyClass();
    }

    var _this = $(this);    

    var msg = 'no message';
    var show = function() {
        alert(msg);
    };    

    // shows an alert after some delay
    this.delayedAlert = function(message) {
        msg = message;
        window.setTimeout(show, 2000);
    };
}

您也可以通过在每次创建MyClass实例时不创建新的函数定义来改进此代码。 将您的方法添加到MyClass的原型中:

(function(window) {

    var MyClass = function() {
        // if this isn't an instance, make it so:
        if (!(this instanceof MyClass)) {
            return new MyClass();
        }
    };

    var msg = 'no message';
    var show = function() {
        alert(msg);
    }; 

    MyClass.prototype.delayedAlert = function(message) {
        msg = message;
        window.setTimeout(show, 2000);
    };

    window.MyClass = MyClass;

})(window);

您可以声明一个匿名函数:

window.setTimeout(function () {
    this.show();
}, 2000);

并且,根据函数的不同,您可以将函数本身传递给setTimeout

window.setTimeout(this.show, 2000);

当您将字符串传递给setTimeout ,基本上是在告诉浏览器等待一定时间,然后eval该字符串。

当浏览eval"this.show()" ,它认为this是指全局对象或window

第一条建议使用闭包 ,第二条建议仅传递函数本身(不执行 !),因为在JavaScript中, 函数是一类对象 ,可以像其他任何变量一样对待。

请记住,当您使用第二种解决方案时,您是在将该方法与其上下文分开。 如果您尝试以下操作...

var msg = 'sadface';

var myObj = {
    msg: 'hello world',
    greet: function () {
        alert(this.msg);
    }
};

window.setTimeout(myObj.greet, 2000);

...然后, this greet不再引用myObj 相反,它将指向window 它会提醒sadface ,不是hello world

祝好运。

暂无
暂无

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

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