【问题标题】:Understanding $.proxy() in jQuery了解 jQuery 中的 $.proxy()
【发布时间】:2011-06-26 13:24:46
【问题描述】:

来自docs 我了解到.proxy() 会更改作为参数传递的函数的范围。有人可以更好地解释一下吗?我们为什么要这样做?

【问题讨论】:

  • 根据文档,“此方法对于将事件处理程序附加到上下文指向不同对象的元素最有用。此外,jQuery 确保即使您绑定返回的函数从 jQuery.proxy() 它仍然会取消绑定正确的函数,如果通过了原始函数”。您觉得缺少的措辞有什么特别之处吗?
  • 这里不清楚 此外,jQuery 确保即使您绑定从 jQuery.proxy() 返回的函数,如果传递了原始函数,它仍然会取消绑定正确的函数“。原始是什么意思?
  • 原始文件是为其创建代理的文件。但是既然你没有完全掌握这些东西,你确定要使用它吗?
  • 这是 nettuts 制作的精彩视频教程,展示了 $.proxy 的工作原理。 http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-learning-jquery-1-4s-proxy/
  • @bzlm ,当我想到这种方法时,我正在阅读 jquery 文档。

标签: javascript jquery


【解决方案1】:

它最终所做的是确保函数中this 的值将是您想要的值。

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

拿着这个:

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

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

但是如果我们想要在添加类之前有一个短暂的延迟呢?我们可能会使用setTimeout 来完成它,但问题是无论我们给setTimeout 提供什么函数,该函数中this 的值都将是window 而不是我们的元素。

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

所以我们可以改为调用$.proxy(),将我们想要分配给this的函数和值发送给它,它会返回一个保留该值的函数。

$('#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 的值之后,它返回了一个确保this 正确设置的函数。

它是如何做到的?它只是返回一个匿名函数,调用我们的函数使用 .apply() 方法,这让它显式设置 this 的值。

返回的函数的简化外观可能如下所示:

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,它所做的只是使用正确的this 上下文执行我们的原始函数。

【讨论】:

  • 使用$.proxy(function () {...}, this)而不是(function() {...}).call(this)有什么价值?有区别吗?
  • @JustinMorgan:使用.call,您将立即调用该函数。使用$.proxy,就像Function.prototype.bind 返回一个新函数。该新函数具有永久绑定的this 值,因此当它被传递给setTimeout 并且稍后setTimeout 调用该函数时,它仍然具有正确的this 值。
  • 这种技术相对于这样的技术有什么优势(如果有的话)? $('#myElement').click(function() { var el = $(this); setTimeout(function() { el.addClass('aNewClass'); }, 1000); });
  • 对于这个例子,你不必使用 $.proxy 方法。相反,你可以像这样简单地重写它 $('#myElement').click(function() { var that = this ; setTimeout(function() { // 通过在处理程序方法范围内声明的变量的新上下文 $(that).addClass('aNewClass'); }, 1000); });
  • 一个匿名用户,拥有 112k 的代表、可怕的 JavaScript/jQuery 知识,并且自 2011 年 10 月以来就没有人见过......也许是 John Resig?
【解决方案2】:

没有更详细的说明(这是必要的,因为这是关于 ECMAScript 中的 Contextthis 上下文变量等)

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

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

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

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

激活对象
作用域链
这个值

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

.call()
.apply()

如果我们有一个函数foobar(),我们可以通过调用来改变this的值:

foobar.call({test: 5});

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

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

这正是jQuery.proxy() 所做的。它接受 functioncontext(它只不过是一个对象)并通过调用 .call().apply() 链接函数并返回该新函数。

【讨论】:

  • 很好的解释,比函数的官方jQuery文档更简单/更好
【解决方案3】:

我写了这个函数:

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); }
}

【讨论】:

    【解决方案4】:

    使用“立即调用函数表达式,简称:IIFE”自执行函数可以实现相同的目标:

        $('#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>

    【讨论】:

    猜你喜欢
    • 2012-11-23
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多