這幾天遇到js參數傳遞方式的問題,深切探究一番,將所得結果總結於此segmentfault
在傳值調用中實際參數被求值,其值被綁定到函數中對應的變量上(一般是把值複製到新內存區域)。在函數返回後調用者做用域裏的曾傳給函數的任何東西都不會變。
在「傳引用調用」求值中,傳遞給函數的是它的 實際參數的隱式引用(即實際參數的地址)而不是實參的拷貝。一般函數可以修改這些參數(好比賦值),並且改變對於調用者是可見的。
在傳共享對象調用中,傳遞給函數的是實參所指向引用對象的地址,而不是實參的地址,即傳遞共享對象。故在函數中修改引用對象時,實參的值也會跟着變化,而若是是從新給新參賦值後,再進行任何修改都不會影響到外面的實參了。
let a = 1; function add(val) { val += 1; console.log(`val=${val}`); // 2 } add(a); console.log(`a=${a}`); // 1
let a = 'hahaha'; function change(val) { val = 'heiheihei'; console.log(`val=${val}`); // heiheihei } change(a); console.log(`a=${a}`); // hahaha
let a = Symbol('prop'); function change(val) { val = Symbol(2); console.log(`val=${val.toString()}`); // Symbol(2) } change(a); console.log(`a=${a.toString()}`); // Symbol(prop)
let obj = { a: 1 } function change(obj) { obj.a = 2; console.log(obj); // {a: 2} obj = { a: 3 } console.log(obj); // {a: 3} } change(obj); console.log(obj); // {a: 2}
從上面的代碼能夠看出,在函數中對參數所指向的對象進行修改時會影響到外面的實參,但對函數參數從新賦值時,不會影響到實參,故js引用類型的傳值方式爲call by sharing函數
在C#
中類型有兩種:值類型和引用類型,它們之間的卻別在於實際數據存儲的位置(如上圖)。值類型的變量和實際數據都存儲在堆棧中;而引用類型則只有變量存儲在堆棧中,變量存儲着實際數據的地址,實際數據存儲在與地址相對應的託管堆中。學習
綜上所述(證實題2333),值傳遞和引用傳遞的參數類型既能夠是值類型又能夠是引用類型,可是call by sharing的參數類型只能是引用類型。spa
我的理解:JS中,null賦值的變量時對象,可是,變量指向的引用地址爲空,故在函數中修改參數的值,對實參不會又任何影響,因此是按值傳遞。string類型應該跟C#按值傳遞的緣由一致。
參考:
維基百科
JS中的值是按值傳遞,仍是按引用傳遞呢
《Learning hard C#學習筆記》第10章code