javascript:关于Function.prototype.bind()这个方法

if(typeofFunction.prototype.bind==="undefined"){Function.prototype.bind=function(this... if(typeof Function.prototype.bind==="undefined"){
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吗?求解
展开
 我来答
墨旭东05G
2013-06-27 · 超过21用户采纳过TA的回答
知道答主
回答量:94
采纳率:0%
帮助的人:67.5万
展开全部

  这里确实是两个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,不会影响函数的性质。

  希望能帮到你。

帐号已注销
2013-04-16 · TA获得超过4630个赞
知道大有可为答主
回答量:1345
采纳率:50%
帮助的人:1635万
展开全部
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可以提供两个参数,都是整型,分别表示要截取的起始和终结下标,终结下标可以省略。

本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式