JavaScript奇妙的題目

前言

JavaScript 在很多地方都非常的奇妙又好玩,過陣子也準備進入 js 奇妙的章節…
先來做一下記錄前陣子在學院中人家的 js 問題。

問題

1
2
3
4
5
6
7
8
9
function f (x){
console.log('inside f:x='+ x );
x = 5;
console.log('inside f:x='+ x + '(after assignment)');
}
let x = 3;
console.log('before calling f: x=' + x);
f(x);
console.log('after calling f: x='+ x);

答案輸出是

1
2
3
4
befre calling f: x=3
inside f:x=3
inside f:x=5(after assignment)
after calling f: x=3

解析

首先因為變數、函式有 Hoisting 特性(若不清楚 Hoisting 可以觀看此篇文章)

所以創造階段會是這樣子

1
2
3
4
let x
function f (x){
...
}

然後 x 先賦予值

1
2
3
4
5
let x
function f (x){
...
}
x = 3

此時 x 代表 3 ,然後下一行執行console.log('before calling f: x=' + x);

所以就會得到以下結果。

1
befre calling f: x=3

接下來因為是執行 function f(x);

此時的 X 帶入至 function 中,所以 X 值為 3 帶入,拆解來看會是這樣子

1
2
3
4
5
function f (3){
console.log('inside f:x='+ 3 );
x = 5;
console.log('inside f:x='+ 5 + '(after assignment)'); // 此時因為X被前面的X所修改,所以會變成5
}

所以答案就會得到

1
2
inside f:x=3
inside f:x=5(after assignment)

執行完之後下一行就是 console.log('after calling f: x='+ x);
通常這邊就很容易搞混都會誤以為 X 會是5,但其實並不會,因為變數 X 在 function 中與全域建立的 X 並無關,所以答案會這樣子

1
after calling f: x=3

順便附上簡易圖解的執行順序

如果要替全域的 X 做變化的話,那就應該在 function 中做 return 回傳

1
2
3
4
5
6
7
8
9
10
11
function f (x){
console.log('inside f:x='+ x );
x = 5;
console.log('inside f:x='+ x + '(after assignment)');
console.log(x)
return x;
}
let x = 3;
console.log('before calling f: x=' + x);
f(x);
console.log('after calling f: x='+ x);

但是在這邊會發現單純的 return 回來 after calling f: x 還是等於3,這是因為 function retrun 之後並沒有東西去接值,所以若要全域的 x 有所變化的話,那就要多一行x = f(x);這樣就可以改變 X 的值了。

1
2
3
4
5
6
7
8
9
10
11
function f (x){
console.log('inside f:x='+ x );
x = 5;
console.log('inside f:x='+ x + '(after assignment)');
console.log(x)
return x;
}
let x = 3;
console.log('before calling f: x=' + x);
x = f(x);
console.log('after calling f: x='+ x);

可以給點牡蠣。
Google AD