测试代码1:
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var objMyInfo={
name:"xx",
sex:"male",
showEvent:function()
{
alert(this);
alert("this->"+this.value);
}
}
//$("#button1").bind("click",objMyInfo.showEvent);//这时候打印[object HTMLButtonElement]和"this->先谢谢"
//proxy函数如果没有绑定第二个参数context,那么这里面的context就是window,也就是函数里面的this指向了window对象!
//var proxy=$.proxy(objMyInfo.showEvent)
// proxy();//打印[object Window]和"this->undefined"
//1,2表示要额外传入showEvent函数的参数,在里面通过arguments对象访问,同时也会把objMyInfo作为this传入该函数
//所以length是3,this指向objMyInfo对象
var to=$.proxy(objMyInfo.showEvent,objMyInfo,1,2);
$("#button1").bind("click",to);
});
</script>
</head>
<body>
<button id="button1" value="先谢谢">点击测试</button>
</body>
</html>
测试代码2:下面我们把jQuery源码中间的proxy函数一部分提出来作为函数调用来测试一下如果第二个参数是字符串的情况:
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
</head>
<body>
<p id="p">在我后面添加</p>
<script type="text/javascript">
function proxy(fn,context)
{
//第二个参数是string也就是执行环境,temp=objPerson("test");
//context=objPerson,fn=temp也就是说这时候的fn就是第一个参数的一个函数属性
if ( typeof context === "string" ) {
tmp = fn[ context ];
context = fn;
fn = tmp;
}
alert("context->"+context.name+"fn->"+fn);
}//proxy函数结束
var objPerson = {
name: "John Doe",
age: 32,
test: function(){
alert("xxx");//我作为context对象objPerson的函数属性
}
}
proxy(objPerson,"test");//打印"John Doe"和function(){alert("xxx")}
</script>
</body>
</html>
note:如果第二个参数是string类型,那么结果就是绑定的函数是第一个对象的相应属性的函数,而这个相应属性的名字由第二个字符串指定!
测试代码3:
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var objMyInfo={
name:"xx",
sex:"male",
showEvent:function()
{
alert(arguments.length);
}
}
var to=$.proxy(objMyInfo.showEvent,objMyInfo,1,2);
//在返回proxy函数之前首先把多余的1,2参数保存下来,这样就形成了一个闭包,下次调用proxy时候可以访问!
to(3,4,5);//打印5,也就是参数个数是5了!这里的3,4,5就是上面的arguments参数!,所以在showEvent函数里面的参数个数是5!
alert(to.guid);//每个函数都有一个guid。这里打印1
});
</script>
</head>
<body>
<button id="button1" value="先谢谢">点击测试</button>
</body>
</html>
proxy函数源码分析:
proxy: function( fn, context ) {
var args, proxy, tmp;
//这是上面提到的第二个参数是string字符串的情况
if ( typeof context === "string" ) {
tmp = fn[ context ];
context = fn;
fn = tmp;
}
// Quick check to determine if target is callable, in the spec
// this throws a TypeError, but we will just return undefined.
//如果第一个参数不是函数,那么直接返回undefined
//因为如果不是函数,但是我们把它当作函数调用,直接返回TypeError异常
if ( !jQuery.isFunction( fn ) ) {
return undefined;
}
// Simulated bind
//获取传递进来的第三个以及以后的参数
args = slice.call( arguments, 2 );
//对proxy函数进行重新赋值,设置为一个新的函数
//fn函数里面的this指向的就是context或者this!默认是当前函数,也就是如果不传递context,那么就是当前函数
proxy = function() {
return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
};
// Set the guid of unique handler to the same of original handler, so it can be removed
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
return proxy;
}