Javascript “正确通过”;这";设置超时回调的上下文?

Javascript “正确通过”;这";设置超时回调的上下文?,javascript,callback,this,settimeout,bind,jquery,underscore.js,ecmascript-5,prototypejs,node.js,Javascript,Callback,This,Settimeout,Bind,Jquery,Underscore.js,Ecmascript 5,Prototypejs,Node.js,如何将上下文传递到setTimeout?我想在1000毫秒后调用this.tip.destroy() if (this.options.destroyOnHide) { setTimeout(function() { this.tip.destroy() }, 1000); } 当我尝试上面的方法时,这个指的是窗口。编辑:总之,在2010年,当我问这个问题时,解决这个问题最常见的方法是保存对执行设置超时函数调用的上下文的引用,因为setTimeout执行函数时this指向全局对象:

如何将上下文传递到
setTimeout
?我想在1000毫秒后调用
this.tip.destroy()

if (this.options.destroyOnHide) {
     setTimeout(function() { this.tip.destroy() }, 1000);
} 

当我尝试上面的方法时,
这个
指的是窗口。

编辑:总之,在2010年,当我问这个问题时,解决这个问题最常见的方法是保存对执行
设置超时
函数调用的上下文的引用,因为
setTimeout
执行函数时
this
指向全局对象:

var that = this;
if (this.options.destroyOnHide) {
     setTimeout(function(){ that.tip.destroy() }, 1000);
} 
在一年前刚刚发布的ES5规范中,它引入了,这在原始答案中没有提出,因为它还没有得到广泛支持,您需要使用polyfills,但现在它无处不在:

if (this.options.destroyOnHide) {
     setTimeout(function(){ this.tip.destroy() }.bind(this), 1000);
}
bind
函数创建一个新函数,其中预先填充了
此值

现在在现代JS中,这正是箭头函数解决的问题:

箭头函数本身没有
this
值,当您访问它时,您正在访问封闭词法范围的
this

HTML5也出现在2011年,现在可以将参数传递给回调函数:

if (this.options.destroyOnHide) {
     setTimeout(function(that){ that.tip.destroy() }, 1000, this);
}
另见:


有现成的快捷方式(语法糖)可以连接到函数wrapper@CMS。(下面假设您想要的上下文是
this.tip


(,Node.js 5.0.0+) 对于几乎所有的javascript开发(2020年),您都可以使用fat-arrow函数,它们是

与函数表达式相比,(也称为胖箭头函数)具有更短的语法,并且在词汇上绑定
this
值[…]

在您的情况下,请尝试以下方法:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}

(,Node.js)和Prototype.js 如果您的目标是或(2020年),这意味着所有常见浏览器以及旧浏览器,您可以使用。您可以选择传递任何要创建的函数参数

同样,在您的情况下,请尝试以下方法:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}
同样的功能也被使用过(任何其他库?)

如果您想要自定义向后兼容性(但请遵守注释)


如果您已经在使用jQuery1.4+,那么有一个现成的函数可以显式设置函数的
this
上下文

:获取一个函数并返回一个始终具有特定上下文的新函数

在您的情况下,请尝试以下方法:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}

, 它可以在underline.js和lodash中找到,如
..bind(…)

将函数绑定到对象,这意味着每当调用函数时,
this
的值都将是对象。(可选)将参数绑定到函数以预填充它们,也称为部分应用程序

在您的情况下,请尝试以下方法:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}
if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}


在Internet Explorer以外的浏览器中,您可以在延迟后将参数一起传递给函数:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
因此,您可以这样做:

var timeoutID = window.setTimeout(function (self) {
  console.log(self); 
}, 500, this);
就性能而言,这比范围查找(将
This
缓存到超时/间隔表达式之外的变量中),然后创建闭包(通过使用
$.proxy
Function.prototype.bind
)要好

使其在IEs中工作的代码来自:

如果正在使用,则可以使用
bind

例如


注意:这在IE中不起作用

var ob = {
    p: "ob.p"
}

var p = "window.p";

setTimeout(function(){
    console.log(this.p); // will print "window.p"
},1000); 

setTimeout(function(){
    console.log(this.p); // will print "ob.p"
}.bind(ob),1000);

它起作用了。我用一个jsbin脚本测试了这个概念:这段代码涉及到生成一个不必要的变量(具有函数范围);如果您正确地将
this
传递给函数,那么对于这种情况,对于map()、forEach()等,您就可以使用更少的代码、更少的CPU周期和更少的内存来解决这个问题***参见:Misha Reyzlin的答案。为什么不默认
函数绑定(上下文…
?我错过了什么吗?每次调用这个函数时,不断地创建一个新函数(bind就是这么做的)是否有效果?我有一个搜索超时,每次按键后都会重置,似乎我应该将这个“绑定”方法缓存到某个地方以供重用。@Triynko:我不认为绑定函数是一个昂贵的操作,但如果多次调用同一个绑定函数,您最好保留一个引用:
var boundFn=fn.bind(此);boundFn();boundFn()