1. 程式人生 > >如何理解JavaScript中的引數按值傳遞

如何理解JavaScript中的引數按值傳遞

開始之前先說一下 ES 中的兩種資料型別的值:基本型別值和引用型別值

基本資料型別:Undefined、Null、Boolean、Number、String。

引用資料型別的值是儲存在記憶體中的物件。與其他語言不同,JavaScript 不允許直接訪問記憶體中的位置,也就是說不能直接操作物件的記憶體空間。在操作物件時,實際上是操作物件的引用而不是實際的物件。 這一部分對下面理解引數傳遞非常重要。


傳遞引數

ECMAScript 中所有函式的引數都是按值傳遞的。 也就是說,把函式外部的值複製給函式內部的引數,就和把值從一個變數複製到另一個變數一樣。

想引數傳遞基本型別的值時,這個值會被複制給一個區域性變數,這很好理解。但是在向引數傳遞引用型別的值時,會把這個值在記憶體中的地址複製給一個區域性變數,因此這個區域性變數的變化會反映在函式外部。

這裡就會出現理解上的問題,既然在區域性作用域中修改的物件會在全域性作用域中反映出來,為什麼不是按引用傳遞呢?

《JavaScript高階程式設計》書中給出的證明是:

function setName1(obj) {
    obj.name = "Talon";
}
var person1 = new Object();
setName1(person1);
alert(person1.name);    // Talon


function setName2(obj) {
    obj.name = "Talon";
    obj = new Object();
    obj.
name = "Jaya"; } var person2 = new Object(); setName2(person2); alert(person2.name); // Talon

書裡給出的解釋是:
如果是按引用傳值,那麼第二個例子中 person 就會自動被修改為指向其 name 屬性值為 “Jaya” 的新物件。但是在接下來訪問 person2.name 時,值仍然是 “Talon”。說明即使在函式內部修改了引數的值,但原始的引用仍保持未變。


如果看到這裡沒有問題,就不需要往下看了,沒準會越看越迷糊。。。。

說實話我當時看完沒看懂。。。
也不是沒懂,是理解錯了,我以為我懂了。

我當時認為,如果是按引用,那麼就會出現書中所說的這種現象。然後就做了個實驗證實:

// 0
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Talon";
alert(obj2.name);   // Talon

// 1
var obj1 = new Object();
obj1.name = "Talon";
var obj2 = obj1;
obj1 = new Object();
obj1.name = "Jaya";
alert(obj2.name);   // Talon

然後實驗結果跟我想象的並不一樣,我以為第二個例子中會輸出 “Talon”。因為我的實驗中使用的是複製,而複製就是按引用複製,書中說 “如果是按引用傳值,那麼第二個例子中 person 就會自動被修改為指向其 name 屬性值為 “Jaya” 的新物件。”

然後我就很納悶,又仔細看了前面講的那些,也就是這篇部落格最上面的內容。

然後就明白了書中的意思。
我理解的和書中所說的都是正確的,只不過沒有 get 到書所說的那個點。我認為他就是傳了地址,所以就是引用。而書中說就是傳的值。
其實都沒有錯,換句話說,確實是傳的值,只不過這個值,就是物件的地址。

So,ECMAScript 中所有函式的引數都是按值傳遞的。
Yes,這句話沒有問題。

可能描述的還是不清楚。。。
emmmm
反正我懂了