javascript中的函数绑定

首先我们来看看jQuery中的proxy函数如何实现函数绑定的:

   proxy: function( fn, context ) {
		var args, proxy, tmp;
		//这说明:在直接调用proxy得到新的函数的时候就可以传入多余的参数,从第三个参数以后会被当作额外的参数来处理
		args = slice.call( arguments, 2 );
		proxy = function() {//这里的arguments就是真正函数调用的时候传入的参数,通过把两次的参数结合调用最终返回的函数!
			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
		};
		return proxy;
	}
例子1:

//在当前页面内追加换行标签和指定的HTML内容
function w( html ){
	document.body.innerHTML += "<br/>" + html;
}
var name = "Hello";
function foo( a, b,c,d ){
	w( this.name );
	w( a + b+c+d );
}
var obj = { name: "CodePlayer", age: 18 };
var proxy = $.proxy( foo, obj, 5, 10 );
//调用proxy函数的时候返回了一个新的函数,该函数的context就是obj,同时因为他是通过闭包完成,所以他会得到外层的args也就是调用,$.proxy时候传入的多余的参数!同时通过闭包也能够访问外层的参数的fn!
// 代理调用foo()函数,此时其内部的this指向对象obj
proxy(5,6);
// CodePlayer
// 26
例子2:

var handler={
	message:"event handle",
	handleCick:function(event)
	{
		alert(this.message);
	}
}
var btn=document.getElementById("button");
//这时候打印"undefined",因为这里面的this指向了button对象,在IE8中会指向window
//buttom对象没有message属性,所以打印undefined!
btn.οnclick=handler.handleCick;
note:在IE8中会指向window,其它浏览器指向button!
例子3:(重点不是闭包,而是修正this,this在这里的指向就是调用者handler)

var handler={
	message:"event handle",
	handleCick:function(event)
	{
		alert(this.message);
	}
}
//那么为什么说这句话修改了this呢,因为this指向的就是调用者!而在这个函数中调用者就是handler
//至于为什么把event传入到handleClick中,是因为在handleClick中可以获取到这个事件的具体信息!
var btn=document.getElementById("button");
btn.οnclick=function(event)
{
	handler.handleCick(event);
	
}
note:例子2和例子3都是针对特定代码进行绑定对象修正的,不具有共性,从而才引入了函数绑定的概念!
例4:

   function show(n1,n2)
	{
	 alert(n1);
	 alert(n2);
	 alert(this);
	}
	$.proxy(show ,document,3,4)();//直接用括号调用
	$.proxy(show,document,3)(4);//调用的时候传入4作为参数
note:上面两种调用方式都是相等的,this指向了document对象。其实在jQuery的源码中处处有函数绑定的影子,下面就是在$.when函数中的代码片段

.done( updateFunc( i, resolveContexts, resolveValues ) )
note:对于特定的Deferred对象,我们在他的回调集合中加入了updateFunc方法调用后的结果,这个结果也是一个函数,而这个返回的函数可以访问updateFunc函数中的所有的参数信息!如i,resolveContexts,resolveValues等!当你用resolve方法传入参数的时候就会被传递到updateFunc调用返回的新的参数中作为arguments!

例5:原生的ECMAScript5的bind方法

 调用者是一个函数,参数是一个对象,表示将这个函数绑定到这个参数中,从而在这个函数中可以用this访问这个参数对象!

var handler={
	message:"event handle",
	handleCick:function(event)
	{
		alert(this.message);
	}
}
var btn=document.getElementById("button");
//这时候就会打印"event handle"
btn.οnclick=handler.handleCick.bind(handler);
//主要用于事件处理程序,setTimeout,setInterval,然而和普通函数相比
//有更多的内存开销,而且因为是多重函数调用稍微慢一点!
例6:

其实关于关于bind方法的博客是很多的,但是从他们对bind的描述来说我们可以知道,bind方法和上面的proxy函数内部具有相似的逻辑。拿着这个函数作为下次真正调用时候执行,把bind时候传入的多于一个的参数作为局部变量args保存下来,然后把它和返回新函数调用的参数组合起来,作为新的参数传入到新函数中!

var slice=Array.prototype.slice;
//返回的是一个本地call方法,这个call方法的上下文是slice方法
//如果你给这个本地call方法传入参数,那么这个参会会被送到原生的call方法中去执行!
var nativeCall=Function.prototype.call.bind(slice);
//打印true,这个nativeCall方法的上下文是slice方法!
alert(nativeCall({0:"xx",1:"ccc"}) instanceof Array);
下面这个例子的本地call方法的上下文就是concat方法( 要调用谁的方法就把谁作为上下文):

var concat=Array.prototype.concat;
//返回的是一个本地call方法,这个call方法的上下文是slice方法
//如果你给这个本地call方法传入参数,那么这个参会会被送到原生的call方法中去执行!
var nativeCall=Function.prototype.call.bind(concat,[1,2,3]);
//打印true,这个nativeCall方法的上下文是slice方法!
alert(nativeCall([4,5,6]));

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值