如何将此上下文传递给一个函数?

259

我以为这是我可以轻松谷歌找到的东西,但也许我没有问对问题...

如何在给定的 JavaScript 函数中设置“this”所指的内容?

例如,就像大多数 jQuery 函数一样:

$(selector).each(function() {
   //$(this) gives me access to whatever selector we're on
});

如何编写/调用具有适当"this"引用的独立函数?我使用jQuery,因此如果有一种特定于jQuery的方法就更理想了。


可能是重复问题:https://dev59.com/-HRB5IYBdhLWcg3wxZ1K#520417 - user123444555621
我知道这是一个老问题,但对于其他来到这里的人,请查看jQuery的$.proxy - RyBolt
5个回答

350

JavaScript的.call().apply()方法允许您为函数设置上下文

var myfunc = function(){
    alert(this.name);
};

var obj_a = {
    name:  "FOO"
};

var obj_b = {
    name:  "BAR!!"
};

现在您可以调用:

myfunc.call(obj_a);

传递obj_a将会弹出FOO。反过来,传递obj_b将会弹出BAR!!.call().apply()之间的区别在于,如果要传递参数给函数,.call()将使用逗号分隔的列表,而.apply()需要一个数组。

myfunc.call(obj_a, 1, 2, 3);
myfunc.apply(obj_a, [1, 2, 3]);
因此,您可以使用apply()方法轻松编写一个hook函数。例如,我们想要向jQuery的.css()方法添加一个功能。我们可以存储原始函数引用,用自定义代码覆盖该函数并调用存储的函数。
var _css = $.fn.css;
$.fn.css = function(){
   alert('hooked!');
   _css.apply(this, arguments);
};

由于魔术arguments对象是类数组对象,因此我们可以直接将其传递给apply()。这样我们就可以保证所有参数都被传递到原始函数中。


6
有趣的小知识:如果你需要反复调用与obj_a相关的函数,你可以通过使用var bound_myfunc = myfunc.bind(obj_a)来创建一个副本,并在需要时简单地调用bound_myfunc() - wbadart

58

使用 function.call 方法:

var f = function () { console.log(this); }
f.call(that, arg1, arg2, etc);

在函数中,that 是你希望 this 所指向的对象。


2
"function" 是一个保留关键字,请考虑更新您的响应以包括命名函数,因为 "function.call(...)" 不是有效的 JavaScript。 - Daniel Allen
1
@DanielAllen:如果我提供的示例函数名称没有定义,代码仍将抛出JS错误。但是,我已更新示例函数名称。 - palswim
太神奇了,非常感谢! - undefined

37

另一个基本例子:

不起作用:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
};
img.src = reader.result;

工作中:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
}.bind(this);
img.src = reader.result;

基本上,只需在您的函数中添加.bind(this)


2
这应该是被接受的答案。语法更简单,对大脑更容易处理...做得好Joery。 - nenea

31

您可以使用bind函数来设置函数内的this上下文。

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"

2
我怀疑目前的正确答案永远不会得到最多的投票。应该有一个选项来查看答案,其中赞成票基于已经过去的时间进行加权。 - Dave F

17

jQuery使用.call(...)方法将当前节点分配给您传递为参数的函数中的this

编辑:

当您有疑问时,不要害怕查看jQuery代码,它都是清晰且有良好文档记录的JavaScript代码。

例如:这个问题的答案在第574行附近,
callback.call( object[ name ], name, object[ name ] ) === false


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接