在看Promise迷你書遇到一段代碼一開始沒有理解,然后就查了一下bind的使用以及函數(shù)的值傳遞與引用傳遞。代碼大致如下:
function recordValue(results, value) {
results.push(value);
return results;
}
var pushValue = recordValue.bind(null, []);
console.log(pushValue(1))
console.log(pushValue(2))
一開始我以為結(jié)果會是
[1]
[2]
但是實際結(jié)果是
[1]
[1,2]
function.prototype.bind
然后以為bind的參數(shù)我理解的有問題,我去查了一下api,下面是bind函數(shù)的解釋。
bind()函數(shù)會創(chuàng)建一個新函數(shù)(稱為綁定函數(shù)),新函數(shù)與被調(diào)函數(shù)(綁定函數(shù)的目標函數(shù))具有相同的函數(shù)體(在 ECMAScript 5 規(guī)范中內(nèi)置的
call屬性)。當新函數(shù)被調(diào)用時 this值綁定到bind()的第一個參數(shù),該參數(shù)不能被重寫。綁定函數(shù)被調(diào)用時,bind()也接受預設(shè)的參數(shù)提供給原函數(shù)。一個綁定函數(shù)也能使用new操作符創(chuàng)建對象:這種行為就像把原函數(shù)當成構(gòu)造器。提供的 this值被忽略,同時調(diào)用時的參數(shù)被提供給模擬函數(shù)。
簡單來說就是改變某個方法內(nèi)部的this指向,同時可以指定該函數(shù)的參數(shù)。我和理解的沒什么大問題,我的理解就是它將recordValue的this綁定為null,并且將第一個參數(shù)綁定為[],所以我會覺得結(jié)果是[1]和[2]。然后我打斷點發(fā)現(xiàn)第二次執(zhí)行pushValue的時候recordValue函數(shù)的第一個參數(shù)變成了[1],不再是[]。所以我就考慮到了函數(shù)的引用傳遞。
然后我試了一下改造一下,結(jié)果和我第一次預期的一樣
function recordValue(results, value) {
results = results+value;
return results;
}
var pushValue = recordValue.bind(null, "");
console.log(pushValue("hello"))
console.log(pushValue("word"))
這個時候結(jié)果又變成了
hello
world
這個時候我再改造一下
function recordValue(results, value) {
results.a = results.a + value
return results;
}
var pushValue = recordValue.bind(null, {a:0});
console.log(pushValue(1)) //
console.log(pushValue(2)) //
//-------結(jié)果----------//
{ a: 1 }
{ a: 3 }
這個時候就明顯的是引用傳遞所以導致的第二次執(zhí)行的時候第一個參數(shù)變了,不再為[]。
最上面的代碼var pushValue = recordValue.bind(null, []);在綁定參數(shù)為[]的時候,相當于初始化一個數(shù)組對象,而數(shù)組不是基本類型,是引用類型,作為函數(shù)的參數(shù)的時候就是引用傳遞。
js的變量類型
js的數(shù)據(jù)類型分為兩種類型:
1.基本類型
包括Undefined, Null, Boolean, Number和String五種基本數(shù)據(jù)類型
2.引用類型
保存在內(nèi)存中的對象們,不能直接操作,只能通過保存在變量中的地址引用對其進行操作
值傳遞
所以當函數(shù)的參數(shù)為基本類型的時候,它將保存的值’hello‘賦值給形參,他們只是值一樣,地址不同。所以函數(shù)體內(nèi)不管怎么改變形參,實參都不會跟著改變

引用傳遞
那么當參數(shù)為引用類型的時候,實參將其內(nèi)部保存的對象的內(nèi)存地址賦值給形參,他們兩個保存的是一個內(nèi)存地址,指向內(nèi)存堆中的同一個對象,有點類似c中的指針。這個時候形參改變了其某個屬性的值的時候其實改變的是指向的內(nèi)存堆中對象的屬性值。所以函數(shù)執(zhí)行完成后,實參內(nèi)存的地址雖然不變,但指向的對象已經(jīng)改變了,所以實參會跟著形參變。

所以函數(shù)執(zhí)行完畢后,實參從[]變成了[1]。
還有一種情況,如果形參在函數(shù)體內(nèi)改變的不是引用的對象,而是重新賦值,比如指向一個新的對象results = {x:1}或者賦值一個基本類型results = 0,那么實參不變。因為指向一個新的變量都是改變形參內(nèi)存中存的值,這個新的值可以是一個基本類型也可能是新的內(nèi)存對象的地址。值變了之后,但實參內(nèi)存中的值還是之前對象的地址,所以和形參不一樣。

其實,引用傳遞也是值傳遞,只是傳遞的是引用罷了。之所以有引用傳遞這種說法應該是為了讓大家更好明白概念。