光明頂開課了 JAVAscript 第一課(預解釋)

混元霹靂手發表於2017-05-17

作者 混元霹靂手-Ziksang

本文章將是一套系列課程,偏進階,面向有JAVAscript基礎的讀者,文章以精簡、通俗意通為主要講解方式,全方位的帶你進入JAVAscript集中知識點學習,讓零散的知識點一步一步的聚攏,希望大家有所收穫!

我們先回顧一下js中的資料型別有那些?

一.基本資料型別
1.number
2.string
3.boolean
4.null
5.undefined
二.引用資料型別
1.object ---- {}物件 ---- []陣列 ---- /^$/正則 ---- Date時間
2.function

基本資料型別和引用資料型別區別在於什麼地方?

1.基本資料型別:是按照值來操作的
2.引用資料型別:是按照引用地址來操作的

看個demo例子

var name = 'ziksang'
var obj = {name : '混元霹靂手', age : "23" }
function demo () {
    console.log('光明頂開課了')
}複製程式碼

1.當HTML載入頁面的時候,提供了一個全域性js程式碼執行的環境 ---- 全域性作用域
在node環境下(global)
在瀏覽器下 (window)

下圖會詳細解釋 以上程式碼的在全域性作用預解釋的執行流程

光明頂開課了 JAVAscript  第一課(預解釋)

如果我們此時把obj.name = '預解釋',此時內部是進行了一個如何的操作?
1.因為obj物件是一個引用型別,所以把全域性作用域下的obj物件 通過xxxfff000地址找到所指向的開闢的記憶體空間,然後把內空間中的name屬性改成‘預解釋’

如果我們執行console.log(demo),此時內部是進行了一個如何的操作?
1.因為demo是一個function,也是一個引用型別,此時會通過xxxfff111地址找到所指向的開闢的記憶體空間,裡面儲存的是一個轉成字串的demo函式體的整體程式碼段,此時就會把整個函式整體程式碼段輸出出來 //function demo(){console.log('光明頂開課了')}

如果我們執行console.log(demo()),此時內部是進行了一個如何操作?
1.因為此時是demo(),函式通過一個()括號,還是會通過xxxfff111地址找到所指向的開闢的記憶體空間,裡面儲存的是一個demo函式體的整體程式碼段,此時會執行裡面的程式碼段,進行兩部操作,第一是執行程式碼段中的程式碼執行程式,會列印出'光明頂開課了',二會返回一個值,返回結果是通過函式程式碼段中return後的結果,如果沒有return則預設返回undefined

預解釋

在當前的作用域中,js程式碼執行之前瀏覽器首先會預設的把所有帶var,let,const的操作符和function進行提前的宣告或者定義

一.理解宣告和定義 【宣告】declare 【定義】defined

先看 var name = 'ziksang'看看瀏覽器引擎給它做了那些預解釋

在預解釋中是分為兩大部分完成的,一部分是宣告,一部分是定義
1.宣告 (代表將要在全域性環境下要宣告一些識別符號,這些將通過你的程式碼來解析) 告訴瀏覽器在全域性環境下通過操作符宣告一個 name識別符號(變數)
2.定義 (代表就是給全域性環境下聲名出來的識別符號(變數)進行定義基本型別引用型別的值name='ziksang'name變數定義了一個string基本型別的值

預解釋的定義

是瀏覽器引擎的一種機制,在當前的作用域當中,程式碼執行之前,瀏覽器分預設把帶識別符號或者function關鍵字的進行提前的宣告和定義。

二.對於識別符號var 和 function關鍵字在預解釋時的區別之處

此時我就可以延伸出一個面試題 請問題1題2分別列印出什麼,請說出原理!

題1

    function demo(){
        console.log(1)
    }
    var demo = function(){
        console.log(2)
    }
    demo()複製程式碼

題2

   var demo = function(){
        console.log(2)
    }
    function demo(){
        console.log(1)
    }
    demo()複製程式碼

題1列印出的是2,題2列印出的還是2....為什麼呢?
首先我們先看看識別符號var 和 function關鍵字在預解釋時的區別之處
在預解釋過程中,識別符號先宣告再定義,而function關鍵字是宣告定義一起完成

先看執行過程的瀏覽器解析和記憶體空間分配圖

光明頂開課了 JAVAscript  第一課(預解釋)

再看看瀏覽器預解釋過程分析和記憶體空間分配圖

光明頂開課了 JAVAscript  第一課(預解釋)

從上面兩個製圖我們可以找到原理,函式表示式用的是識別符號宣告的,預解釋層的第一層宣告層只是對操作符demo變數進行宣告,而函式宣告function demo在宣告層不但宣告而且還進行了定義,導致在定義層的的時候,函式表示式覆蓋了函式宣告,所以題1題2都列印出來是2

三.預解釋導致變數提升

這些問題也很能考成一個面試題,還是對預解釋的理解

console.log(name)
var name = 'ziksang'
console.log(name)
demo()
function demo(){
   console.log('光明頂開課啦')
}複製程式碼
看看執行預解釋流程圖

光明頂開課了 JAVAscript  第一課(預解釋)

首先預解釋,先不執行裡面的程式碼,提前先解析的是宣告層,把用識別符號和function關鍵字宣告的變數或者函式宣告先提前解析宣告

此時name先進入宣告層,先宣告一個var name,再宣告一個function demo,同時函式宣告在宣告層同時進行了定義,那就是把整個function demo(){console.log(‘光明頂開課了’)}提到了程式碼最頂層的解釋層的宣告層裡,此時從上往下執行程式碼,第一個執行到console.log(name),因為name只是進行了變數提升到瞭解釋層的宣告層並沒有定義,如果沒有定義則就是undefined;程式碼再往下走,name進行了定義直接進入了定義層,name定義為'ziksang',此時再執行到console.log(name),則返回‘ziksang’,程式碼往下走,執行到demo()的時候,函式宣告已經提到了解釋層的宣告層並且進行了定義,所以執行demo()並不會報錯,而且會返回'光明頂開課啦'

總結,這裡講解了對瀏覽器預解釋的認識,並且通過預解釋認識到變數提升的原因,對識別符號和function宣告的函式的區別有了一定的認識,更加深入的瞭解了宣告和定義的一個生命週期

沒有經過本人同意不得轉載,如果經過本人同意轉載後請標註出自@混元霹靂手-ziksang

相關文章