javascript:关于Function.prototype.bind()这个方法
Function.prototype.bind=function(thisArg){
var fn=this,
slice=Array.prototype.slice,
args=slice.call(arguments,1);//arguments1
return function(){
return fn.apply(thisArg,args.concat(slice.call(arguments)));//arguments2
}
};
}
这里的arguments是同一个arguments吗?求解 展开
这里确实是两个arguments,而且这两个arguments是不同的。
首先你要理解prototype里bind()函数的含义,bind()函数和apply()、call()函数一样,都是用来改变函数的上下文环境(即函数中this所指代的对象),与之不同的是,apply()和call()都是立即执行获取结果,而bind()可以返回一个已经改变了上下文环境的函数,供日后调用。而这个函数本身是有参数的,这里bind()函数就是可以在函数获取上下文环境时给其传参,同时也可以在函数调用时给其传参,所以这里会有两个arguments。
举个例子吧,比方你有一个可变基数的累加函数:
var add = function() {
var sum = this.base
for (var i = 0, c; c = arguments[i++];)
sum += c
return sum
}
在这个函数中,基数值base是通过上下文环境决定的,如果基数是1,那么add(1)的结果就是2,如果基数是10,那么add(1)的结果就是11。当然本函数的参数是可变的,当基数为10时,你也可以这么写:add(1,2,3,4),其结果为10+1+2+3+4=20。
那函数的上下文环境怎么决定呢?就是题主所提到的bind()函数。下面我们规定两个上下文:
var context1 = {
base: 1
}
var context2 = {
base: 10
}
这样当你就可以通过bind创造一个基数为1和基数为10的累加函数:
var addbase1 = add.bind(context1, 9)
var addbase10 = add.bind(context2)
什么?你问我为什么addbase1在bind的时候会有两个参数(context1、9)?因为这里其实等于我在bind的同时就给addbase1这个函数开始传参啦,这个就是题主题目中的第一个arguments。还记得那个切片arguments.slice(1)么?就是把提供上下文的参数context1切掉了,保留了传给addbase1的参数9。
当然,在定义了函数之后我也可以正常传参,如:
addbase1(1, 2, 3, 4) //结果为20
addbase10(1, 2, 3, 4) //结果也是20
这里的1,2,3,4就是题主所谓的第二个arguments,而我们看到函数addbase1的结果和addbase10的结果一样,就是因为在bind函数里有一行concat,将我们两次传入的arguments结合了起来,使得addbase1的过程变成:1(基底)+9(第一次传参)+1+2+3+4 = 20
但是要注意的时,第一次传参的arguments和第二次传参的arguments是不同的,因为第一次传入的参数会被保存在函数的闭包中,成为一种currying的属性,不会随着以后的传参而改变(即保存在了代码第五行的args中)。也就是说,当你再次执行如下代码时:
addbase1(1, 2, 3, 4) //结果依然是20,实际上addbase1和addbase10一样了
实际上也就是说,在bind时传入的参数,也就是第一个arguments,会影响函数的属性;在调用时传入的参数,也就是第二个arguments,不会影响函数的性质。
希望能帮到你。
Function.prototype.bind=function(thisArg){
var fn=this,
slice=Array.prototype.slice,
args=slice.call(arguments,1);//arguments1
var a1 = arguments;
return function(){
alert(a1 == arguments);// 判断是否为同一个
return fn.apply(thisArg,args.concat(slice.call(arguments)));//arguments2
}
};
((function(){}).bind())(2);// 总是alert出false
不是。第一个arguments是只thisArg,第二个则是指返回的那个函数的arguments。
Function.prototype.bind=function(thisArg){
var fn=this,
slice=Array.prototype.slice,
args=slice.call(arguments,1);//arguments1
alert(arguments[0]);// alert出1
return function(){
alert(arguments[0]);// alert出2
return fn.apply(thisArg,args.concat(slice.call(arguments)));//arguments2
}
};
((function(){}).bind(1))(2);
大哥麻烦问下
最后的为什么还要concat(slice.call(arguments))呢?有什么用呢呢?
concat是数组类型的一个方法,其功能是将参数arg拼接到数组对象上。例如
var arr = [1,2,3];
arr = arr.concat([4,5]);
alert(arr);// 结果为1,2,3,4,5
而slice.call(arg)其实就arg.slice()。slice也是数组类型的一个方法,它返回的是数组的一部分,当然还是一个数组。slice可以提供两个参数,都是整型,分别表示要截取的起始和终结下标,终结下标可以省略。