在 jQuery 中理解 $. xy ()

医生我了解到,.proxy()将改变作为参数传递的函数的作用域。有人能给我解释一下吗?我们为什么要这么做?

64381 次浏览

它最终要做的是确保函数中 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上下文执行我们的原始函数。

没有进入更多的细节(这将是必要的,因为这是关于 背景在 ECMAScript,这个上下文变量等。)

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

  • 全球环境
  • 函数上下文
  • 评估上下文

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

函数的每个调用都进入函数执行上下文:

激活对象
范围链
此值

因此,这个值是一个与执行上下文相关的特殊对象。ECMA-/Javascript 中有两个函数可能会在函数执行上下文中更改 这个值:

.call()
.apply()

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

foobar.call({test: 5});

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

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

这正是 jQuery.proxy()所做的。它接受一个 functioncontext(只是一个对象) ,通过调用 .call().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); }
}

同样的目标可以通过使用“立即调用函数表达式,简短: 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>