今天看到了一道很有意思的面試題,在聽完老師的講解后,我決定也和大家講講這道題
var x = 0
function foo(x, y = function() { x = 3; console.log(x) }) {
console.log(x)
var x = 2
y()
console.log(x)
}
foo()
console.log(x)
大家可以想想這道題的答案是什么?
😎😎😎好 時間到
接下來我來講講這道題
要想做對這道題 我們得先知道一個概念
函數中的參數如果有默認值的情況下,那么他是會形成一個參數作用域的
或許有小伙伴會不相信,為啥你說會形成作用域就形成作用域呢?
那么 我們來看下官方ecma給出的解釋是什么?
小伙伴們,可以仔細讀一讀這一段話.我簡單翻譯一下
如果函數的形參不包含任何默認的值,那么函數作用域將會與參數共享一個作用域
如果默認參數存在的話,那么會形成一個參數作用域
好滴 我們現在分析下
var x = 0;
//函數有默認值的時候 會形成一個參數作用域
function foo(x, y = function () { x = 3; console.log(x) }) {
//第一個輸出的時候 會先去尋找函數內部作用域有沒有x的聲明
//小伙伴可能會有疑惑,這個var申明的不是會有變量提升嘛?
//我來解釋一下 如果有默認值的話 x會先去參數作用域尋找
//顯然 在這個之前是沒有聲明的 所以會去函數尋找默認值形成的參數作用域
//這時候 x的值是 undefined
console.log(x);
var x = 2;
//執行y 這時候的y函數內的值是去尋找參數作用域內的x
//給參數作用域內的x 賦值為3 所以輸出為3
y();
//最后這個輸出x 在函數內的作用域尋找
//找到了var x=2 這個聲明
//所以輸出2
console.log(x);
}
foo();
// 這個輸出x是去尋找全局的x
//這時候的全局x=0 輸出為0
console.log(x);
好 我們現在已經分析完了 大家可以仔細看看
總體而言還是比較簡單的