理解jQuery中的$ .proxy()?

从docs我明白, .proxy()将改变作为parameter passing函数的范围。 有人可以更好地解释我,我们为什么要这样做?

它最终做的是确保this函数的价值将成为你所期望的价值。

一个常见的例子是在click处理程序中发生的setTimeout

拿着它:

 $('#myElement').click(function() { // In this function, "this" is our DOM element. $(this).addClass('aNewClass'); }); 

意图很简单。 当myElement被点击时,它应该得到类aNewClass 。 处理程序内部表示被点击的元素。

但是如果我们想在join课程之前想要短暂的延迟呢? 我们可能使用setTimeout来完成它,但麻烦的是,无论我们给setTimeout的函数, this函数内部的值将是window而不是我们的元素。

 $('#myElement').click(function() { setTimeout(function() { // Problem! In this function "this" is not our element! $(this).addClass('aNewClass'); }, 1000); }); 

所以我们可以做的就是调用$.proxy() ,并将函数和值分配给它,它将返回一个保留该值的函数。

 $('#myElement').click(function() { // ------------------v--------give $.proxy our function, setTimeout($.proxy(function() { $(this).addClass('aNewClass'); // Now "this" is again our element }, this), 1000); // ---^--------------and tell it that we want our DOM element to be the // value of "this" in the function }); 

所以在给了$.proxy()这个函数和我们想要的值之后,它返回了一个函数来确保this函数被正确设置。

它是如何做到的? 它只是返回一个匿名函数,它使用.apply()方法调用我们的函数,它可以明确地设置这个值。

返回函数的简化看起来可能如下所示:

 function() { // v--------func is the function we gave to $.proxy func.apply( ctx ); // ----------^------ ctx is the value we wanted for "this" (our DOM element) } 

所以这个匿名函数给了setTimeout ,它所做的就是用适当的上下文执行我们原来的函数。

没有进入更多的细节(这将是必要的,因为这是关于ECMAScript中的上下文这个上下文variables等)

在ECMA- / Javascript中有三种不同types的“上下文”:

  • 全球背景
  • 函数上下文
  • 评估上下文

每个代码都在其执行上下文执行 。 有一个全局上下文,函数(和eval)上下文可以有很多实例。 现在有趣的部分:

每个函数调用都会进入函数执行上下文。 函数的执行上下文如下所示:

激活对象
范围链
这个值

所以这个值是一个与执行上下文相关的特殊对象。 在ECMA- / Javascript中有两个函数可以在函数执行上下文中改变这个值:

 .call() .apply() 

如果我们有一个函数foobar()我们可以调用这个值来调用:

 foobar.call({test: 5}); 

现在我们可以在foobar访问我们传入的对象:

 function foobar() { this.test // === 5 } 

这正是jQuery.proxy()所做的。 它需要一个functioncontext (除了一个对象之外的东西),并通过调用.apply().apply()链接函数并返回这个新函数。

我写了这个函数:

 function my_proxy (func,obj) { if (typeof(func)!="function") return; // If obj is empty or another set another object if (!obj) obj=this; return function () { return func.apply(obj,arguments); } } 

使用自动执行function可以达到同样的目标:

  $('#myElement').click(function() { (function(el){ setTimeout(function() { // Problem! In this function "this" is not our element! el.addClass('colorme'); }, 1000); })($(this)); // self executing function }); 
 .colorme{ color:red; font-size:20px; } 
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <script src="https://code.jquery.com/jquery-3.1.0.js"></script> <div id="myElement">Click me</div> </body> </html>