這是一個很有趣的議題,至少我查了網路不好找到(因為我找不到,只好自己測試了)
底下這邊是一段JS的CODE,可以看一下後,想像它的結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
myname = "global"

var setup = function (a,b){

console.log(myname);
console.log(b);
console.log(a);

var myname = "local";
var a = 1;
function b(){
console.log("function!");
}
var b = function(){
console.log("hi");
}
console.log(a);
console.log(myname);
}

setup(5,6);

這段CODE牽扯到function的hoisting,如果這邊不知道是甚麼,建議就先去GOOGLE一下這個關鍵字。
而這段CODE的輸出會如下方表示:

1
2
3
4
5
6
7
-> undefined
-> function b(){
console.log("function!");

}
-> 5
-> 1
-> local

來一一解釋。照一般網路上寫的hoisting的話,變數的宣告以及具名函式的宣告實作都會往上提到最前面,因此應該會變成下面這個樣子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
myname = "global"

var setup = function (a,b){
var myname;
var a;
var b;
function b(){
console.log("function!");
}
console.log(myname);
console.log(b);
console.log(a);

myname = "local";
a = 1;

var b = function(){
console.log("hi");
}
console.log(a);
console.log(myname);
}

setup(5,6);

經過這樣的測試,也可以發現變數宣告會被提到比具名函示宣告實作還要上面,不然一開始的console.log(b)的輸出結果,就不會是一個function物件,而是undefined了。
這邊myname則就是基本概念一樣,因為被重新宣告了,所以外面的全域變數,就不會是這個setup function所指到的變數,因此console.log(myname)就會是undefined(畢竟只有宣告,卻沒有說他是甚麼)
而這邊最好玩的莫過於a這個變數,以及本文中要介紹的function傳入後的參數會在甚麼時候指派給對應的變數。在變數b的介紹時,刻意沒有去提到,大家會發現,我在執行setup這個function的時候,是有傳入參數的,分別是5和6,而在function中接的變數名稱則是a和b。從結果可以發現,傳入的參數並不會比宣告變數還在指派給對應的變數,因為如果是這樣的話,第一個console.log(a)所輸出的結果也應該是undefined,但是他偏偏是5,而第一個console.log(b)卻不是6,而是我們的具名函式,因此,我們總結一下,參數傳入以後會在hoisting過的變數宣告之後,但在具名函式宣告實作之前。統整後的結果就會是下面這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
myname = "global"

var setup = function (a,b){
var myname;
var a;
var b;
a = a; //(後面的a是function傳入的參數,例子中的5)
b = b; //(後面的b是function傳入的參數,例子中的6)
function b(){
console.log("function!");
}
console.log(myname);
console.log(b);
console.log(a);

myname = "local";
a = 1;

var b = function(){
console.log("hi");
}
console.log(a);
console.log(myname);
}

setup(5,6);

每次看完這些規則後的結論就是,不要把變數的名稱都取一樣就不會有困擾了。