JavaScript函式引數傳遞

大魔王薩格拉斯發表於2015-11-16

Hello,今天和大家分享下JS中的一個基本概念:函式引數傳遞!

 

先來看看一個DEMO

 

 1 var str="hello world";
 2 
 3 function func(s){
 4     s="hello javascript";
 5 }
 6 
 7 
 8 func(str);
 9 
10 console.log(str);

 

請問這裡控制檯最終將輸出什麼?

答案是:hello world.

也就是說func函式並沒有修改全域性作用域中的str值。這個例子比較好理解,JS的函式引數傳遞是按值傳遞,只不過這裡的值是指棧區的值。

這裡函式將str的值傳遞給函式內部變數s,然後修改了內部變數s的值,顯然這和全部作用域中的str並沒有什麼關係,所以str仍然是初始值。

除非這裡我們顯示呼叫並修改全域性作用域下的變數:

function func(s){
     window.str="hello javascript";  
}

 這樣全域性作用域下的str變數才會被修改。

 

 

好了,再來看第二個DEMO:

 1 var obj={
 2     attr:'obj attr value'
 3 };
 4 
 5 function func(o){
 6     o.attr="new attr value!";
 7 }
 8 
 9 func(obj);
10 
11 console.log(obj.attr);

這一次我們將函式傳遞的引數換成了一個物件,輸出結果又是什麼呢?

答案是:new attr value! 也就是說我們的obj這個全部作用域的物件被修改了,為什麼?

原因還是第一個DEMO加粗標註的那句話:JS的函式引數傳遞是按值傳遞,只不過這裡的值是指棧區的值。

對於物件來說,傳遞的值是物件在堆區的地址。(關於JS變數儲存原理歡迎檢視:http://www.cnblogs.com/souvenir/p/4969399.html

回到DEMO2,第9行呼叫func函式傳遞過去就是obj物件的堆區地址,然後這個地址又複製給了func內部作用域的o物件,

也就是說,o與obj都指向了同一個物件,所以修改o屬性的以後,再次訪問obj,當然也發生了變化!

 

 

OK,這個沒有問題以後,我們再來看另一個DEMO:

 1 var obj={
 2     attr:'obj attr value'
 3 };
 4 
 5 function func(obj){
 6     obj={attr:'new attr value!'};
 7 }
 8 
 9 func(obj);
10 
11 console.log(obj.attr);


這個DEMO是在第二個DEMO的基礎上進行修改得到的,在函式內部我們不是修改obj物件的屬性,而是修改obj整個物件。

可能大家會受到上面第二個DEMO的影響,認為這裡的全部變數obj仍然被修改了。

答案是,obj並未被修改,輸出的值仍然是:obj attr value。

眼尖的同學會發現這個DEMO其實和第一個DEMO並沒有什麼不同,只不過一個傳遞的是普通型別,一個傳遞的物件。

對。這裡只是將一個新的物件的引用地址賦值給了obj,但是千萬別忘了,obj這是func的區域性變數,和全部變數obj也沒有半毛錢關係。

當然,除非我們這麼修改的話,情況就不一樣了。

function func(obj){
    window.obj={attr:'new attr value!'};
}


 總結:

  JS的函式引數傳遞是按值傳遞。

  JS的函式引數傳遞是按值傳遞。

  JS的函式引數傳遞是按值傳遞。

 

  (嗯,重要的事情要說三遍)

 

相關文章