搜尋
首頁web前端js教程JavaScript專題之一:變數提升與預編譯

JavaScript專題之一:變數提升與預編譯

目錄

  • #前言
  • 一、有趣的現象
  • 二、Js的預解析
  • 三、提升之間的優先權
  • 四、ES6
  • 寫在最後

##(相關免費學習推薦:

javascript影片教學

#前言

    本篇文章是《JavaScript專案進階系列》的第一篇文章,全系列大概會包含例如:
  • 防抖節流
  • #深淺拷貝
  • 數組去重
  • 排序

等等經典的專案知識點。取名為專案進階是因為它們在許多場合的「出鏡率高」很高,為了避免化身

google內容搜尋師

,《JavaScript專案進階系列》誕生了! ! ! JavaScript專題之一:變數提升與預編譯

一、有趣的現象

#依照大家的常識,JavaScript程式碼在執行是一定是自上而下的,你需要輸出一個字串,當然需要事先宣告一個

保存string類型的變數
。如果深奧的道理我都能懂,於是我閱讀了下面的程式碼。

1.1 我以為的開局

var str = '123';console.log(str); // 123

我們調換程式碼的位置在再看:

console.log(str); // undefinedvar str = '123';

我好像找到規律了!!!

#當我看完了前兩段程式碼並且進行了「深度思考」後,我好像找到規律了,那就是:在當前程式碼區塊後函數中,在變數宣告和初始化

之前

使用變量,會拿不到正確的值。 JavaScript專題之一:變數提升與預編譯

1.2 其實是這樣的

帶著上面的「結論」我來到了這裡

var val = '余光';(function(){
    console.log(val); // 余光})();
果然如此! ,在

變數宣告和初始化之後

耶穌也阻擋不了我拿到val的值,我說的! ! !

當我看到下面一段程式碼時,我已經產生了動搖,此事必要蹊蹺。

var val = '余光';(function(){
    console.log(val); // undefined
    var val = '测试';})();

Ps:如果大家立即執行函數有疑問,不妨看看《JavaScript之深入理解立即調用函數表達式(IIFE)》吧~

這…我慫了,是什麼原因導致這樣的現象發生的呢? Js又是如果處理的呢? JavaScript專題之一:變數提升與預編譯

二、Js的預解析

在目前的作用域內,無論在哪裡變數聲明,在幕後,都會進行一次看不見的移動。 注意:僅宣告被「移動」。即聲明和賦值在某些時候被動分開了。而這次看不見的移動其實就是

Js在編譯階段的解析

來看一段《你知不知道的Js》中經典的例子:

name = '余光'; // 未添加关键字(未声明),name为全局变量,,即window.name = '余光'var name; // 再次声明name,此时name未进行初始化,它的值是undefined吗?console.log(name); // ?
結果是成功打印“余光”,這樣

看不見的移動
就發生在Js預解析(編譯)之中。

2.1 核心:預解析

為了搞清楚這個核心問題,我們需要回顧一下,引擎會在解釋JavaScript程式碼之前先將其編譯。編譯階段中的一部分工作就是找到所有的聲明,並用適當的作用域將它們關聯起來。有興趣的小夥伴可以閱讀《JavaScript中的變數物件》和《從作用域到作用域鏈》這兩篇文章哦~因此,發生這樣的事情,包括變數函數在內的所有宣告都會在任何程式碼被執行前先被處理。當你看到

var a = 2
    ;時,可能會認為這是一個宣告。但JavaScript實際上會將其看成兩個聲明:var a;和a = 2;。
  • 第一個定義宣告是在編譯階段進行的。
第二個賦值宣告會被留在原地等待執行階段。

即程式碼是這樣寫的:

// 我们看到的代码:var name = '余光';

但Js會將它解析成:

// 声明(Declaration)var name; // 声明但未初始化,所以分配 undefined// 初始化(Initialization)name = '余光'; // 初始化(赋值)
所以本小結的一段程式碼應該這樣分析:
var name; // 声明name提到作用域顶部,并被分配了一个undefinedname = '余光'; // 进行初始化操作console.log(name); // '余光'

2.2 注意:只有宣告被提升了

只有宣告會被提升,而賦值和其他程式碼邏輯會在執行到程式碼的位置時才會生效

。所以會有下面的問題:

foo();function foo(){
    console.log(name); // undefined
    var name = '余光';}
函數被提升了,自然可以正常執行,但變數只是宣告被提升了。

2.3 每個作用域都會進行提升操作

還是上面的程式碼:

foo();function foo(){
    console.log(name); // undefined
    var name = '余光';}

實際上它在編譯時是這樣的:JavaScript專題之一:變數提升與預編譯

function foo(){
    var name; // 声明
    console.log(name); // undefined
    name = '余光'; // 初始化}foo(); // 函数执行

三、提升之間的優先權

既然我們知道了變數

函數###會被提升,他們之間又是如何判斷優先順序的呢? ###
3.1 函数会被首先提升,然后才是变量

我们分析下面的代码:

foo();var foo; // 1function foo(){
    console.log('余光');}foo = function(){
    console.log('小李');}

本着函数优先提升的原则,他会被解析成这样:

function foo(){
    console.log('余光');}foo(); // 余光foo = function(){
    console.log('小李');}

注意,var foo 因为是一个重复声明,且优先级低于函数声明所以它被忽略掉了。

3.2 函数字面量不会进行函数提升

最直观的例子,就是在函数字面量前调用该函数:

foo();var foo = function(){
    console.log(1);}// TypeError: foo is not a function

这段程序中:

  1. 变量标识符foo被提升并分配给所在作用域(在这里是全局作用域),因此在执行foo()时不会导致ReferenceError(),而是会提示你 foo is not a function
  2. 然后就是执行foo,foo此时并没有赋值(注意变量被提升了)。由于对undefined值进行函数调用而导致非法操作,因此抛出TypeError异常。

四、ES6和小结

ES6新增了两个命令letconst,用来声明变量,有关它们完整的概念我会在《ES6基础系列》中总结,提起它们,是因为变量提升在它们身上不会存在

4.1 变量提升是可以规避的

let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

// var 的情况console.log(foo); // 输出undefinedvar foo = 2;// let 的情况console.log(bar); // 报错ReferenceErrorlet bar = 2;

上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

在变量提升上,const和let一样,只在声明所在的块级作用域内有效,也不会变量提升

4.2 小结
  1. 变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部,但变量的初始化不会提升;
  2. 函数提升:函数声明可以被看作是函数的整体被提升到了代码的顶部,但函数字面量表达式并不会引发函数提升;
  3. 函数提升优先与变量提升;
  4. let和const可以有效的规避变量提升

最后提炼一下:JavaScript引擎并不总是按照代码的顺序来进行解析。在编译阶段,无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理,这个过程被称为提升。声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会提升。

相关免费学习推荐:javascript(视频)

以上是JavaScript專題之一:變數提升與預編譯的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:CSDN。如有侵權,請聯絡admin@php.cn刪除
Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

JavaScript是用C編寫的嗎?檢查證據JavaScript是用C編寫的嗎?檢查證據Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript的角色:使網絡交互和動態JavaScript的角色:使網絡交互和動態Apr 24, 2025 am 12:12 AM

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具