1. 程式人生 > 程式設計 >JavaScript中變數提升和函式提升例項詳解

JavaScript中變數提升和函式提升例項詳解

執行

  • 詞法分析階段:包括分析形參、分析變數宣告、分析函式宣告三個部分。通過詞法分析將我們寫的 js 程式碼轉成可以執行的程式碼。
  • 執行階段

變數提升

  • 只有宣告被提升,初始化不會被提升
  • 宣告會被提升到當前作用域的頂端

🌰 1:

console.log(num)
www.cppcns.comvar num
num = 6

預編譯之後

var num
console.log(num) // undefined
num = 6

🌰 2:

num = 6
console.log(num)
var num

預編譯之後

var num
num = 6
console.log(num) // 6

🌰 3:

function bar() {
    if (!foo) {
        var foo = 5
    }
    console.log(foo) // 5
}
bar()

預編譯之後

function bar() {
    var foo // if語句內的宣告提升
    if (!foo) {
        foo = 5
    }
    console.log(foo)
}
bar()

函式提升

  • 函式宣告和初始化都會被提升
  • 函式表示式不會被提升

🌰 1: 函式宣告可被提升

console.log(square(5)) // 25
function square(n) {
    return n * n
}

預編譯之後

function square(n) {
    return n * n
}
console.log(square(5))

🌰 2: 函式表示式不可被提升

console.log(square) // undefined
console.log(square(5)) // square is not a function
var square = function(n) {
    return n * n
}

預編譯之後

var square
console.log(square)
console.log(square(5))
square = function() {
    return n * n
}

🌰 3:

function bar() {
    foo() // 2
    var foo = function() {
        console.log(1)
    }
    foo() // 1
    function foo() {
        console.log(2)
    }
    foo() // 1
}
bar()

預編譯之後:

function bar() {
    var foo
    foo = function foo() {
        console.log(2)
    }
    foo() // 2
    foo = function() {
        console.log(1)
    }
    foo() // 1
    foo() // 1
}

函式提升在變數提升之前

🌰 1:

console.log(foo) // 會打印出函式

function foo() {
    console.log('foo')
}
var foo = 1

🌰 2:

var foo = 'hello' // hello
;(function(foo) {
    console.log(foo)
    var foo = foo || 'world'
    console.log(foo) //hello
})(foo)
console.log(foo) // hello

預編譯之後

var foo = 'hello'
;(function(foo) {
    var foo
    foo = 'hello' // 傳入引數的foo值
    console.log(foo) // hello
    foo = foo || 'world' // foo有值為hello,所以沒有賦值為world
    console.log(foo) // hello
})(foo)
console.log(foo) // hello,列印的事全域性作用域下的var foo = 'hello'

JS變數提升和函式提升的順序

最近筆試時碰到考察變數提升與函式提升順序的一道題目,之前只知道var定義的變數會有變數提升以及函式宣告也會提升,但沒有深入研究他們的順序以及詳細過程。事後查閱資料加上自己的驗證,得出了自己對於它們順序的一些理解,話不多說,直接進入正題。

首先給出我的結論:函式提升優先順序高於變數提升,且不會被同名變數宣告時覆蓋,但是會被同名變數賦值後覆蓋

大家可以看下面這段程式碼:

     console.loMPpLZg(a) // ƒ a(){}  變數a賦值前列印的都會是函式a
     var a=1;
     function a(){}
     console.log(a) // 1    變數a賦值後列印的都會是變數a的值

首先變數和函式宣告都提升,但函式提升優先順序高於變數,都提升後變數只是定義沒有賦值,所以輸出的是函式a。詳細過程如下:

     function a(){}  // 函式宣告提升 a-> f a (){}
     var a;        // 變數提升
     console.log(a)  // 此時變數a只是宣告沒有賦值所以不會覆蓋函式a --> 輸出函式a  f a (){}
     a=1;     //變數賦值
     console.log(a)  // 此時變數a賦值了 --> 輸出變數a的值 1

總結:由於函式宣告和變數都會提升,如果函式與變數同名,那麼只要在變數賦值前列印的都會是函式,在變數賦值之後列印都是變數的值。

現在讓我們再看一段程式碼:

     a();  // 2
     var a = function(){  // 看成是一個函式賦值給變數a
        console.log(1)
     }
     a(); // 1
     function a(){
        console.log(2)
     }
     a(); // 1

其實只是想告訴大家只有函式宣告才會提升函式表示式不會提升,所以在函式表示式後面的程式碼會輸出1,因為變數a賦值後把提升的函式a覆蓋了。詳細過程如下:

     function a(){      // 函式提升
         console.log(2)
     }
     var a;   // 變數提升
     a();    // 2  
     a = function(){    // 變數a賦值後覆蓋上面的函式a
         console.log(1)
     }
     a(); // 1
     a(); // 1

再看一段程式碼:

     a();
     function a(){
         console.log(1)
     }
     function a(){
         console.log(2)
     }

列印的是2,道理很簡單先宣告的會被後宣告的覆蓋。

總結

到此這篇關於中變數提升和函式提升的文章就介紹到這了,更多相關js變數提升和函式提升內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!