JavaScript的坑(二)

上一篇文章:JavaScript的坑(一)有興趣的可以看看哦!

var a = 1;
function foo() {
    if (!a) {
        var a = 2;
    }
    alert(a);
};

foo(); // 輸出2,不是1!

alert(a)在執行的時候,會去尋找變量a的位置,它從當前作用域開始向(或者說向外)一直查找到頂層作用域為止,若是找不到就報undefined。
因為在alert(a)的同級作用域里,我們再次聲明了本地變量a,所以它報2;所以我們可以把本地變量a的聲明向下(或者說向內)移動,這樣alert(a)就找不到它了。像下面那樣:

var a = 1;
function foo() {
    if (!a) {
        (function() {        // 這是 IIFE,它會創建一個新的函數作用域
            var a = 2;       // 并且該作用域在 foo() 的內部,所以 alert 訪問不到
        }());               // 不過這個作用域可以訪問上層作用域哦,這就叫:“閉包”
    };
    alert(a);
};
foo();//輸出1

記住:JavaScript 只有函數作用域!

function test() {
    foo();
    //函數聲明
    function foo() {
        alert("我是會出現的啦……");
    }
}
test();//輸出我是會出現的啦……
function test() {
    foo();
    //函數表達式
    var foo = function() {
        alert("我不會出現的哦……");
    }
}
test();//報錯:Uncaught TypeError: foo is not a function

在第一個例子里,函數 foo 是一個聲明,既然是聲明就會被提升。函數聲明會連通命名和函數體一起被提升至作用域頂部。
在第二個例子里,被提升的僅僅是變量名foo,至于它的定義依然停留在原處。因此在執行foo()之前,作用域只知道foo的命名,不知道它到底是什么,所以執行會報錯(通常會是:undefined is not a function)。這叫做函數表達式(Function Expression)

函數表達式只有命名會被提升,定義的函數體則不會。
函數聲明會在js解析器解析時候率先解析,保證其他代碼執行之前,函數可用。而函數表達式必須要等到代碼解析器解析到他所在代碼行,才會被解釋執行。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容