2 回答
TA貢獻2012條經驗 獲得超12個贊
這里確實是兩個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) //結果為20addbase10(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,不會影響函數的性質。
希望能幫到你。
TA貢獻1802條經驗 獲得超4個贊
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); |
添加回答
舉報
