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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ES6之---读懂let才能少踩坑

發布時間:2025/4/5 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ES6之---读懂let才能少踩坑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

開聊吧!(前面一小部分大佬們可以自動忽略)

首先,打臉我的無知!

在剛接觸ES6的時候,我就「以為」我理解了let。然后漫長的自學道路上,let一次又一次的讓我認識到了自己的無知。

希望寫了這篇文章之后能用我的無知,讓在這條道路上的人能少踩些坑。


初識let

和很多人一樣,在聽說了ES6很好用之后,就馬不停蹄的去學習這門充滿著語法糖的東西。開始抱著emmmm快速把es6過一遍的念頭去了菜鳥教程(因為覺得這里的教程很簡潔,但是希望大家以后慎重選擇初學教程!!!)

如圖所示,這就是我對他的初始理解---一個解決javascript沒有塊級作用域的東西。嗯....就是這樣也僅此而已。

let淺解

《1》let 聲明的變量的作用域是塊級的;

{let a = 10;var b = 1; }a // ReferenceError: a is not defined. b // 1 復制代碼

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

說說這個「塊級作用域」里面的坑吧!!!

首先,用阮大神的一個示例來說說過第一個坑

var a = []; for (var i = 0; i < 10; i++) {a[i] = function () {console.log(i);}; } a[6](); 復制代碼

輸出幾呢?是6嗎? 答案是10

為什么呢?因為上面代碼中,變量i是var命令聲明的,在全局范圍內都有效,所以全局只有一個變量i。每一次循環,變量i的值都會發生改變,而循環內被賦給數組a的函數內部的console.log(i),里面的i指向的就是全局的i。也就是說,所有數組a的成員里面的i,指向的都是同一個i,導致運行時輸出的是最后一輪的i的值,也就是 10。

那么怎么解決呢? ES6之前的解決方式--構造閉包形成不銷毀的作用域保存變量

var a = []; for (var i = 0; i < 10; i++) {(function (arg) {a[i] = function () {console.log(arg);}})(i); } a[6](); //6 復制代碼

ES6的解決方式

var a = []; for (let i = 0; i < 10; i++) {a[i] = function () {console.log(i);}; } a[6](); // 6 復制代碼

代碼中,變量i是let聲明的,當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變量,所以最后輸出的是6。 用ES5的代碼描述就是這樣的!

"use strict";var a = [];var _loop = function _loop(i) {a[i] = function () {console.log(i);}; };for (var i = 0; i < 10; i++) {_loop(i); } a[6](); // 6 復制代碼

再來一個平常碼代碼經常會遇到的,面試也會經常遇到。

var liList = document.querySelectorAll('li') // 共5個li for( var i=0; i<liList.length; i++){liList[i].onclick = function(){console.log(i)} } 復制代碼

打印多少呢?0,1,2,3,4 還是 5,5,5,5,5? 相信大家大家應該都知道依次點擊 li 會打印出 5 個 5。

如果把 var i 改成 let i,就會分別打印出 0、1、2、3、4:

var liList = document.querySelectorAll('li') // 共5個li for( let i=0; i<liList.length; i++){liList[i].onclick = function(){console.log(i)} } 復制代碼

闡述一下我的理解吧!

  • for( let i = 0; i< 5; i++) 這句話的圓括號之間,有一個隱藏的作用域。
  • for( let i = 0; i< 5; i++) { 循環體 } 在每次執行循環體之前,JS 引擎會把 i 在循環體的上下文中重新聲明及初始化一次。
  • 用ES5的代碼描述就是這樣的!
'use strict';var liList = document.querySelectorAll('li'); // 共5個livar _loop = function _loop(i) {liList[i].onclick = function () {console.log(i);}; };for (var i = 0; i < liList.length; i++) {_loop(i); } 復制代碼

總結:希望大家在已有遇到跟循環 異步事件之類的問題的時候多注意下,不要掉坑里了?

《2》let 聲明的變量不存在變量提升,有暫時性死區;

先來解釋解釋這兩個吧

變量提升

console.log(foo); // 輸出undefined console.log(bar); // 報錯ReferenceErrorvar foo = 2; let bar = 2; 復制代碼

let不像var那樣會發生“變量提升”現象。所以,變量一定要在聲明后使用,否則報錯。

暫時性死區

let x = 'global' {console.log(x) // Uncaught ReferenceError: x is not definedlet x = 1 } 復制代碼

存在全局變量x,但是塊級作用域內let又聲明了一個局部變量x,導致后者綁定這個塊級作用域,所以在let聲明變量前,對tmp賦值會報錯。

在詳細的解釋這個問題之前,我們先來弄懂ES6之前,我們的作用域里的變量預解釋。

var a = 1; function b(params) {var c = 2; console.log(params); }console.log(a); b(3); 復制代碼

紅色框框中的部分是在b函數被調用的時候才會按照預解釋規則一步步產生,現在寫出來是為了方便你們理解。正因為b函數被預先聲明且賦值了,所以在b函數之前調用他就能得到結果,代碼如下,相信你又學到不少吧!

b(3); function b(params) {var c = 2; console.log(params); }復制代碼

然后就是函數執行的第二步了

夠清楚!!!!夠明了吧!!!

這個我們弄清楚了 就再把let的說一遍 那么上面的問題你自然就豁然開朗了。

關于let的是這樣的

<1>找到所有用 let 聲明的變量,在環境中「創建」這些變量

<2>開始執行代碼(注意現在還沒有初始化也沒有假裝賦值為undefined)

<3>執行 let聲明的變量時,將 該變量 「初始化直接賦值」

現在關于上面的不存在變量提升,有暫時性死區你應該都懂了吧。關于暫時性死區是因為let聲明的變量有塊級作用域而且沒有變量提升所以就產生了

也來看看暫時性死區在es6之前的環境里是怎樣的吧。

//es6中 let x = 'global' {console.log(x) // Uncaught ReferenceError: x is not definedlet x = 1 }//之前版本的環境中 'use strict';var x = 'global'; {console.log(_x); // Uncaught ReferenceError: x is not definedvar _x = 1; }復制代碼

《3》let 不能重復聲明已存在的變量

這個知識點就基本沒啥坑了 自己注意點兒就好

// 報錯 function () {let a = 10;var a = 1; }// 報錯 function () {let a = 10;let a = 1; } 復制代碼

總結

總共也就三個知識點:完全掌握還是要多用!!!

1、let的塊級作用域!

2、let聲明的變量不存在變量提升,有暫時性死區!

3、let聲明的變量不允許重復聲明,無論重復用var或者其他聲明都不行!

let的故事就這樣暫時說完啦(瘋狂求有位大佬來帶帶我啊) 不知不覺又晚上10點多了 該回寢室了 哈哈 如果學到了就給我個小心心吧 哈哈哈

總結

以上是生活随笔為你收集整理的ES6之---读懂let才能少踩坑的全部內容,希望文章能夠幫你解決所遇到的問題。

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