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的函數參數傳遞是按值傳遞。
(嗯,重要的事情要說三遍)
