日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【面试题】【ES6】let和const命令 (面试必看)

發布時間:2024/3/13 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【面试题】【ES6】let和const命令 (面试必看) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??給大家推薦一個實用面試題庫

1、前端面試題庫 (面試必備) ? ? ? ? ? ?推薦:★★★★★

地址:前端面試題庫

1、let命令

基本用法

用法類似于var,但是所聲明的變量,只在let命令所在的代碼塊內有效。

let只能出現在當前作用域的頂層。

在for循環中,使用let聲明循環變量i,當前的i只在本輪循環有效,每一次循環的i都是一個新的變量。

for循環還有一個特別之處,就是設置循環變量的那部分是一個父作用域,而循環體內部是一個單獨的子作用域。

不存在變量提升現象

變量提升:變量可以在聲明之前使用,使用var聲明的變量會自動提升到函數作用域頂部。

==》具體爭議轉看下文“關于是否存在變量提升的爭議問題”

暫時性死區

只要塊級作用域內存在let命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。

var tmp = 123;if (true) {tmp = 'abc'; // ReferenceError 受到let約束let tmp; } 復制代碼

ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。

在代碼塊內,使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區”(temporal dead zone,TDZ)

在沒有引入let前typeof是絕對安全,不會出錯的?typeof對于沒有聲明的變量會顯示undefined不會報錯,但是對于未聲明的變量會報錯ReferenceError

總之,暫時性死區的本質就是,只要一進入當前作用域,所要使用的變量就已經存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現,才可以獲取和使用該變量。

不允許重復聲明

注意區分重復冗余聲明和嵌套聲明

2、塊級作用域

存在意義

ES5只有全局作用域和函數作用域

解決以下場景問題:

  • 內層變量可能會覆蓋外層變量。
  • 用來計數的循環變量泄露為全局變量。
  • ES6的塊級作用域

    let為JavaScript新增了塊級作用域。
    ES6允許塊級作用域的任意嵌套。
    內層作用域可以定義外層作用域的同名變量。

    塊級作用域的出現,實際上使得獲得廣泛應用的**匿名立即執行函數表達式(匿名 IIFE)**不再必要了。

    塊級作用域與函數聲明

    ES5 規定,函數只能在頂層作用域和函數作用域之中聲明,不能在塊級作用域聲明。

    ES6 引入了塊級作用域,明確允許在塊級作用域之中聲明函數。ES6 規定,塊級作用域之中,函數聲明語句的行為類似于let,在塊級作用域之外不可引用。
    為了避免塊級作用域內聲明的函數的處理規則對老代碼產生很大的影響,減輕不兼容問題,ES6允許瀏覽器有自己的行為方式,規則如下:

    • 允許在塊級作用域內聲明函數。
    • 函數聲明類似于var,即會提升到全局作用域或函數作用域的頭部。
    • 同時,函數聲明還會提升到所在的塊級作用域的頭部。

    注意,上面三條規則只對?ES6 的瀏覽器實現有效,其他環境的實現不用遵守,還是將塊級作用域的函數聲明當作let處理。

    根據這三條規則,瀏覽器的 ES6 環境中,塊級作用域內聲明的函數,行為類似于var聲明的變量。
    考慮到環境導致的行為差異太大,應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。

    // 塊級作用域內部的函數聲明語句,建議不要使用 {let a = 'secret';function f() {return a;} }// 塊級作用域內部,優先使用函數表達式 {let a = 'secret';let f = function () {return a;}; } 復制代碼

    ES6 的塊級作用域必須有大括號,如果沒有大括號,JavaScript 引擎就認為不存在塊級作用域。

    3、const命令

    基本用法

    const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。

    const一旦聲明變量,就必須立即初始化,不能留到以后賦值。

    const的作用域與let命令相同:只在聲明所在的塊級作用域內有效。

    const命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置后面使用。

    const聲明的常量,也與let一樣不可重復聲明。

    本質

    const實際上保證的,并不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。

    對于簡單數據類型,值就是保存變量的內存地址【常量】;復合數據類型,變量指向的內存地址保存的只是一個指向實際數據的指針

    const只能保證這個指針是固定的(即總是指向另一個固定的地址),至于它指向的數據結構是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心。

    因此使用const聲明一個對象,對象的屬性是可變的,但是不能改變對象為另一個對象(不能改變指針的指向)。

    凍結對象,無法改變對象屬性應該使用Object.freeze方法。

    var constantize = (obj) => {Object.freeze(obj);Object.keys(obj).forEach( (key, i) => {if ( typeof obj[key] === 'object' ) {constantize( obj[key] );}}); }; 復制代碼

    ES6聲明變量的六種方法

    ES5

  • var
  • function
  • ES6

  • let
  • const
  • import
  • class
  • 4、頂層對象的屬性

    頂層對象,在瀏覽器環境指的是window對象,在 Node 指的是global對象。

    ES5 之中,頂層對象的屬性與全局變量是等價的。

    頂層對象的屬性與全局變量掛鉤帶來的問題:

  • 首先是沒法在編譯時就報出變量未聲明的錯誤,只有運行時才能知道(因為全局變量可能是頂層對象的屬性創造的,而屬性的創造是動態的);
  • 其次,程序員很容易不知不覺地就創建了全局變量(比如打字出錯);
  • 最后,頂層對象的屬性是到處可以讀寫的,這非常不利于模塊化編程。
  • 另一方面,window對象有實體含義,指的是瀏覽器的窗口對象,頂層對象是一個有實體含義的對象,也是不合適的。
  • 從 ES6 開始,全局變量將逐步與頂層對象的屬性脫鉤。

    • var命令和function命令聲明的全局變量,依舊是頂層對象的屬性;
    • let命令、const命令、class命令聲明的全局變量,不屬于頂層對象的屬性。

    5、globalThis對象

    JavaScript 語言存在一個頂層對象,它提供全局環境(即全局作用域),所有代碼都是在這個環境中運行。

    但是,頂層對象在各種實現里面是不統一的。

    • 瀏覽器里面,頂層對象是window,但 Node 和 Web Worker 沒有window。
    • 瀏覽器和?Web Worker?里面,self也指向頂層對象,但是 Node 沒有self。
    • Node?里面,頂層對象是global,但其他環境都不支持。

    很難找到一種方法在所有情況下都取到頂層對象,因此ES2020引入了globalThis作為頂層對象。

    關于是否存在變量提升的爭議問題

    在學習該部分知識時,依據的是ES6入門教程以及MDN中文文檔的內容,沒有過多參看其他官方文檔,便斷定let和const不存在變量提升。但經過大佬指點后拜讀了mdn英文文檔,文檔中描述了對let、const和class來說是存在變量提升的,以下做詳細解釋。

    MDN英文文檔說明存在以下三種認為是變量提升(Hositing)的行為:

    【原文】Hoisting is not a term normatively defined in the ECMAScript specification. The spec does define a group of declarations as?HoistableDeclaration, but this only includes?function,?function*,?async function, and?async function*?declarations. Hoisting is often considered a feature of?var?declarations as well, although in a different way. In colloquial terms, any of the following behaviors may be regarded as hoisting:

    【翻譯】Hosting(變量提升)不是 ECMAScript 規范中規范定義的術語。該規范確實將一組聲明定義為HoistableDeclaration,但這僅包括函數,函數*,異步函數和異步函數*聲明。變量提升通常也被認為是var聲明的一個特征,盡管方式不同。通俗地說,有下列行為之一,可視為變量提升:

  • Being able to use a variable's value in its scope before the line it is declared. ("Value hoisting")
  • 【翻譯】能夠在聲明變量的行之前在其范圍內使用變量的值。(“值變量提升”)

    【實例】ECMAScript規范說明中寫到作為HoistableDeclaration的四種function聲明:function,?function*,?async function和async function*

  • Being able to reference a variable in its scope before the line it is declared, without throwing a?ReferenceError, but the value is always?undefined. ("Declaration hoisting")
  • 【翻譯】能夠在聲明該變量的行之前在其作用域中引用該變量,而不會引發ReferenceError,但該值始終未定義。(“聲明變量提升”)

    【實例】var命令的變量提升

  • The declaration of the variable causes behavior changes in its scope before the line in which it is declared.
  • 【翻譯】變量的聲明會導致在聲明它的行之前在其作用域中發生行為更改。

    【實例】let、const和class聲明命令(也統稱為詞匯聲明lexical declarations)

    看到這里有個問題:既然存在變量提升,為何ES6入門和MDN中文文檔中都沒有注明呢?

    MDN英文文檔也給出了解釋:

    因為暫時性死區的存在,嚴格禁止了在變量聲明前進行使用,所以很多地方都認為let、const和class聲明命令不存在變量提升。這種異議也合理的,因為變量提升并不是一個被定義到ECMAScript中的普遍認可的術語(universally-agreed term)。但是暫時性死區可能會導致其范圍內發生其他可觀察到的變化,這表明是存在著變量提升的。

    實例如下:

    【原文】If the?const x = 2?declaration is not hoisted at all (as in, it only comes into effect when it's executed), then the?console.log(x)?statement should be able to read the x value from the upper scope. However, because the?const?declaration still "taints" the entire scope it's defined in, the?console.log(x)?statement reads the?x?from the?const x = 2?declaration instead, which is not yet initialized, and throws a?ReferenceError. Still, it may be more useful to characterize lexical declarations as non-hoisting, because from a utilitarian perspective, the hoisting of these declarations doesn't bring any meaningful features.

    【翻譯】如果說?const x = 2的聲明完全沒有被變量提升(那么它只在執行時生效),那么console.log(x)應該是能夠從上層作用域中讀取到x的值的。但此處因為const的聲明依然“污染”到了它定義的整個作用域,所以console.log(x)語句實際上讀取到的是const x = 2?聲明的x,并拋出ReferenceError。盡管如此,將詞匯聲明(lexical declarations)?描述為非變量提升可能更有用,因為從功利的角度來看,這些變量提升不會帶來任何有意義的特征。

    【注意】以下這種情況不屬于變量提升:

    {var x = 1; } console.log(x); // 1 復制代碼

    因為這里沒有“先訪問后聲明”,這里只是因為var聲明沒有在塊范圍內。

    結論

    綜上所述,實際上let、const是存在變量提升的,但通常不會刻意去這樣描述,因為從功利的角度來看,這些變量提升并不會帶來任何有意義的特征。

    ??給大家推薦一個實用面試題庫

    1、前端面試題庫 (面試必備) ? ? ? ? ? ?推薦:★★★★★

    地址:前端面試題庫

    總結

    以上是生活随笔為你收集整理的【面试题】【ES6】let和const命令 (面试必看)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。