对javascript中的’this’关键字感到困惑

我很长一段时间没有使用过Javascript,今天就一直在刷新自己。 总是有一件事我是this关键字。 我知道在jQuery事件处理程序中,例如click事件, this指的是触发事件的元素。 this是如何传递给我作为回调给它的函数,即使我的函数没有参数?

给出以下代码:

 $("tr.SummaryTbRow").data("Animating", false); $("tr.SummaryTbAltRow").data("Animating", false); $("tr.SummaryTbRow").click(function () { if ($(this).data("Animating") == false) { if ($(this).next(".Graph").css("display") == "none") { $(this).data("Animating", true); //Part I am questioning. setTimeout(function () { $(this).data("Animating", false); }(this), 550); $(this).next(".Graph").slideRow('down', 500); } else { $(this).data("Animating", true); $(this).next(".Graph").slideRow('up', 500); } } }); 

我试图弄清楚如何将类SummaryTbRow的元素表行SummaryTbRow给我的setTimeout回调函数。 jQuery是否通过我的匿名回调function以类似的方式传递了this ? 我的thisfunction是否参考了我传入的内容?

我知道我可以这样做:

 setTimeout(function (element) { $(element).data("Animating", false); }(this), 550); 

但是我想知道jQuery如何能够将它传递给我的回调函数,即使我的函数有0个参数。

简短回答:

您可以使用函数的.apply().apply()方法在函数上设置this

答案很长:

任何函数上的this变量都与arguments变量类似(这可能是你不知道的事情)。 它在调用函数时设置,并且是调用函数的工件。 为了解释,让我先从论证的arguments 。 考虑:

 myFunction = function () { return arguments.length; }; 

现在让我们看一下对myFunction的一些调用:

 myFunction(); //is 0 myFunction(null); //is 1 myFunction(undefined); //is 1 myFunction(0, 0, 0, 0, 0); //is 5 

正如您所看到的, arguments.length的值不依赖于我们编写函数的方式和位置,而是取决于我们如何调用函数。 this变量也是如此(也称为“调用对象”)。 设置调用对象的确有3种方法(在ES5中有一种排序,但我们会忽略它):

  1. 你可以通过使用点符号调用函数来设置它(例如something.myFunction()
  2. 您可以使用函数的.apply().apply()方法设置它(例如myFunction.call(someObject)
  3. 如果没有使用方法#1或#2设置它,它将默认为全局对象(例如window

所以大多数人都习惯了方法#1。 如果将函数指定为对象的属性,则使用object和dot-notation调用函数,然后将对象设置为this 。 像这样:

 var myFn = (function () { return this.x }); var myObj = { x: 1, y: myFn }; myObj.myFn(); //is 1 

但是我们也可以使用方法2,如果myFn不是我们想要调用它的对象的属性,但是对象遵循正确的forms让myFn能够对它进行操作(参见:duck typing):

 var myOtherObj = { x: 2 } myFn.call(myOtherObj); //is 2 myFn.apply(myOtherObj); //is 2 myFn.apply({ x : 3}); //is 3 

很酷,嗯? 这就是jQuery如何做到的。 当他们执行你的回调时,他们使用.apply(event.target) (将其设置为事件的目标对象)。 由于他们的callbacks框架,他们以更复杂的方式做到了, 但这个想法就在那里 。

无论如何,如果我没有对方法#3进行解释,那么我就不会提供一个很长的答案,这会让一些人完全疯狂:如果你没有设置调用对象会发生什么?

因为所有全局变量都是全局对象的隐式属性,所以您可以从方法#3获得一些有趣的效果。 如:

 var x = 4; myFn(); //is 4 

但是大多数时候你没有幸运地让你的全局对象满足函数对其调用对象的要求,所以通常它只会导致错误和很多挫败感。

可能比你想要的更多,但希望你现在对调用对象及其狡猾的方式更加了解。

要回答你的最后一个问题,你可以将你选择的接收器传递给javascript函数,用于例如:

 someFunction.call(someObject); 

someFunction里面, this将是someObject

在你的情况下,你似乎想要的是

 setTimeout(function (element) { $(element).data("Animating", false); }, 550, this); // this will be passed as element to the callback 

或( 更兼容 )

 var _this = this; setTimeout(function () { $(_this).data("Animating", false); }, 550); 

您可以使用fn.callfn.apply调用函数,这两个函数都使用用于this的上下文参数。

应用 , 调用和绑定方法可用于此目的。 在你的情况下,你只需写:

 setTimeout(function() { $(this).data("Animating", false); }.bind(this), 550);