理解 jQuery 中的 $.proxy()

IT技术 javascript jquery
2021-02-24 15:44:17

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

4个回答

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

一个常见的例子是在setTimeout接受一个内部进行click处理。

拿着这个:

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

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

但是如果我们想要在添加类之前短暂延迟怎么办?我们可能会使用 asetTimeout来完成它,但问题是无论我们给 什么函数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上下文中执行我们的原始函数

@JustinMorgan:.call您正在立即调用该函数。使用$.proxy,就像Function.prototype.bind它返回一个新函数一样。该新函数具有this永久绑定值,因此在将其传递给setTimeoutsetTimeout稍后调用该函数时,它仍将具有正确的this值。
2021-04-21 15:44:17
一个匿名用户,拥有 112k 代表,可怕的 JavaScript/jQuery 知识,自 2011 年 10 月以来就没有出现过……也许是 John Resig?
2021-04-23 15:44:17
使用$.proxy(function () {...}, this)而不是的value是什么(function() {...}).call(this)有区别吗?
2021-05-01 15:44:17
与此类技术相比,这种技术有什么优势(如果有)?$('#myElement').click(function() { var el = $(this); setTimeout(function() { el.addClass('aNewClass'); }, 1000); });
2021-05-05 15:44:17
您不必为此示例使用 $.proxy 方法。相反,您可以简单地像这样重新编写它 $('#myElement').click(function() { var that = this; setTimeout(function() { / / 通过在处理程序方法范围内声明的变量的新上下文 $(that).addClass('aNewClass'); }, 1000); });
2021-05-15 15:44:17

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

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

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

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

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

Activation Object
Scope Chain
这个值

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

.call()
.apply()

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

foobar.call({test: 5});

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

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

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

优秀的解释,比官方的 jQuery 文档更简单/更好
2021-05-04 15:44:17

我写了这个函数:

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

使用“立即调用函数表达式,简称: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>

这通常称为“立即调用函数表达式”(IIFE)而不是“自执行函数”,请参阅en.wikipedia.org/wiki/Immediately-invoked_function_expression
2021-05-19 15:44:17