理解jQuery中的$ .proxy()

Adi*_*kla 167 javascript jquery

从我理解的文档中,.proxy()它将改变作为参数传递的函数的范围.请问有人能更好地向我解释一下吗?我们为什么要这样做?

use*_*716 377

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

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

拿着这个:

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

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

但是如果我们在添加课程之前想要一个短暂的延迟呢?我们可能会使用a setTimeout来完成它,但问题是无论我们给出什么函数,函数内部setTimeout的值this都将window取代我们的元素.

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

所以我们可以做的是调用$.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
});
Run Code Online (Sandbox Code Playgroud)

因此,在我们给出$.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)
}
Run Code Online (Sandbox Code Playgroud)

所以这个匿名函数被赋予了setTimeout,它所做的就是用适当的this上下文执行我们的原始函数.

  • @JustinMorgan:使用`.call`你立即调用该函数.使用`$ .proxy`,它就像`Function.prototype.bind`,它返回一个新函数.这个新函数将`this`值永久绑定,因此当它传递给`setTimeout`,`setTimeout`稍后调用该函数时,它仍将具有正确的`this`值. (11认同)
  • 一个匿名用户拥有112k代表,可怕的JavaScript/jQuery知识,自2011年10月以来一直没见过...... John Resig也许? (3认同)
  • 如果有的话,这种技术的优点是什么呢?$('#myElement').click(function(){var el = $(this); setTimeout(function(){el.addClass('aNewClass');},1000);}); (2认同)

jAn*_*ndy 49

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

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

  • 全球背景
  • 功能上下文
  • 评估背景

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

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

激活对象
范围链
此值

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

.call()
.apply()
Run Code Online (Sandbox Code Playgroud)

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

foobar.call({test: 5});
Run Code Online (Sandbox Code Playgroud)

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

function foobar() { 
    this.test // === 5
}
Run Code Online (Sandbox Code Playgroud)

这正是这样jQuery.proxy()做的.它需要一个functioncontext(它只是一个对象)并通过调用.call().apply()返回该函数来链接该函数.