jQuery源码阅读7:作用域代理proxy()

jQuery里的proxy代理是: 函数在指定作用域中的执行的闭包
要是想限定函数的执行上下文, proxy就特别有用了

一:用法

1
2
3
4
5
6
7
8
9
10
11
12
//目标作用域
var obj = {
name: "rt",
test: function() {
console.log(this);
}
};
//下边两种写法一样, 都是对的
$("#test").click( $.proxy( obj, "test" ) );
$("#test").click( $.proxy( obj.test, obj ) );
//下边这个是不指定作用域的
//$("#test").click( obj.test ); //事件里的this永远是$("#test"),也就是拿不到obj.test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//用proxy指定作用域
$('#myElement').click( function() {
console.log("this1==>"+this);//目标Dom的HTMLDivElement
setTimeout( $.proxy( function() {
console.log("this2==>"+this);//还是目标Dom的HTMLDivElement
},this ), 1000);
} );
//没有指定作用域
$('#myElement').click( function() {
console.log("this3==>"+this);//目标Dom
setTimeout(function() {
console.log("this4==>"+this);//不用proxy会指向window对象
}, 1000);
});

二:源码阅读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 博文作者:ruantao1989@gmail.com
* 引自博客:ruantao.duapp.com/blog
*/
//全局编号
guid: 1,
//==>源码757行
//代理: 返回传入函数在传入作用于上的闭包
proxy: function( fn, context ) {
var tmp, args, proxy;
//第二个参数如果是string的话, 就要调换一下传入参数的顺序
//内部调成( 函数 , obj )的形式
if ( typeof context === "string" ) {
tmp = fn[ context ];
context = fn;
fn = tmp;
}
//验错, 不传入函数
if ( !jQuery.isFunction( fn ) ) {
return undefined;
}
//切割第三个传参以后的传参
args = core_slice.call( arguments, 2 );
//闭包保存一个函数
proxy = function() {
//核心是用apply绑定作用域,
//第二个参数组装一个数组, 把第三个参数之后的参数放在前边,先传入apply
return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
};
//指定id, 如果指定过,就还继续沿用id, 新的旧的id++了
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
//返回闭包引用
return proxy;
},

至此工具函数就差一个access没仔细读, 这个access操作属性都会用, 比如attr() css() html()什么的,
下一个阅读的主题就是属性操作的, 到时候再细读