从docs我明白.proxy()
会改变作为参数传递的函数的范围。请问有人能更好地向我解释一下吗?我们为什么要这样做?
答案 0 :(得分:373)
它最终做的是确保函数中this
的值将是您想要的值。
一个常见的例子是setTimeout
内部click
处理程序。
拿这个:
$('#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
});
的值,它将返回一个保留该值的函数。 / p>
$.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
,它所做的只是使用正确的{{1}}上下文执行我们的原始函数。
答案 1 :(得分:49)
没有详细说明(这是必要的,因为这是关于ECMAScript中的上下文,此上下文变量等)
ECMA- / Javascript中有三种不同类型的“上下文”:
每个代码都在执行上下文中执行。有一个全局上下文,并且可以有许多函数(和eval)上下文的实例。现在有趣的部分:
函数的每次调用都会进入函数执行上下文。函数的执行上下文如下所示:
激活对象
范围链
此值
所以 this 值是一个与执行上下文相关的特殊对象。 ECMA- / Javascript中有两个函数可能会更改函数执行上下文中的 this 值:
.call()
.apply()
如果我们有一个函数foobar()
,我们可以通过调用
foobar.call({test: 5});
现在我们可以在foobar
中访问我们传入的对象:
function foobar() {
this.test // === 5
}
这正是jQuery.proxy()
的作用。它需要function
和context
(它只是一个对象)并通过调用.call()
或.apply()
来链接该函数并返回该新函数。
答案 2 :(得分:4)
我写过这个函数:
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); }
}
答案 3 :(得分:1)
使用“立即调用函数表达式,简称: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>