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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ES6-2 块级作用域与嵌套、let、暂行性死区

發(fā)布時間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ES6-2 块级作用域与嵌套、let、暂行性死区 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

注意,寫在開頭

function test(x = 1) {var x // 不報錯console.log(x) } function test1(x = 1) {let x = 10 // 報錯console.log(x) }

let的變量名不可以和參數(shù)中的名稱相同。而var并不限制,說白了就是希望你規(guī)范使用變量名。
形參原則上數(shù)組函數(shù)內(nèi)部的臨時變量,但是形參其實在內(nèi)存中有獨立的空間存儲。

阮一峰ES6 - let

思考,在編寫代碼時,有es5、es6的語法,究竟是否有塊級作用域?
ES6 明確規(guī)定,如果區(qū)塊中存在let和const命令,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。

1. var關鍵字可以重復聲明

var num1 = 1; var num1 = 100; console.log(num1) // 100

2. let塊級作用域

2.1 同一作用域下不能重復聲明(無論是let/var/const聲明)

let num1 = 1; var num1 = 100; // 報錯 重復定義 var a = 10; let a = 10; // 報錯 function test(a){let a = 10; // 預編譯時,形參a已定義,重復聲明報錯 } let a = 1; function a() { } // 報錯 let a = 1; {function a() { } // 不報錯 } // 函數(shù)提升是在當前(塊級)作用域下提升 // 轉譯后 "use strict";var a = 1; {var _a = function _a() {}; // 不報錯} function test(a) {{let a = 10;}console.log(a) // undefined } test()

2.2 let不會提升,會產(chǎn)生一個暫時性死區(qū),在變量聲明前訪問會報錯

var a = a; console.log(a) // undefined let x = x; // 報錯 // 在變量x的聲明語句還沒有執(zhí)行完成前,就去取x的值,導致報錯”x 未定義“。 // 這里不要把賦值語句拆分為聲明和賦值2步理解
  • 以下3種情況
var x = 1; {// 此處=右的x取的是塊級作用域內(nèi)的// 暫時性死區(qū)let x = x;console.log(x) // 報錯// Uncaught ReferenceError: Cannot access 'x' before initialization }

// 轉譯ES5 "use strict";var x = 1; {var _x = _x;console.log(_x); // undefined }

這里注意: 因為es5不存在暫時死區(qū)。let x = x 的問題在于,右側x是取值并賦值的操作,而這個時候在es6里,x并沒有完成初始化,所以取值x的時候就會失敗。
而var是不存在這種問題的。因為es6嚴格規(guī)定了初始化流程就是變量聲明必須初始化且不允許取值。也就是說聲明語句不可以有對該變量的引用。

轉譯并不能百分百還原。對應let轉var這里就出現(xiàn)了以上的情況。
有些瀏覽器不支持塊級作用域(大括號)。
轉譯結果和babel的版本也有關系,有可能轉譯后去除了大括號或轉成IIFE或其他形式。

var x = 1; {let x;x = x;console.log(x) // undefined }

"use strict";var x = 1; {var _x;_x = _x;console.log(_x); // undefined } // 這個本身就是ES5不需要轉 var x = 1; {x = x;console.log(x) // 1 } let a ; a = a console.log(a) // undefined if (true) {// TDZ開始tmp = 'abc'; // ReferenceErrorconsole.log(tmp); // ReferenceErrorlet tmp; // TDZ結束console.log(tmp); // undefinedtmp = 123;console.log(tmp); // 123 } function bar(x = y, y = 2) {return [x, y]; }bar(); // 報錯 // 參數(shù)x默認值等于另一個參數(shù)y,而此時y還沒有聲明,屬于“死區(qū)”。如果y的默認值是x,就不會報錯,因為此時x已經(jīng)聲明了。

2.3 typeof不再是一個百分之百安全的操作

typeof x; // ReferenceError let x;

注意

for (var i = 0; i < 10; i++) {arr[i] = function () {console.log(i)} } for (var i = 0; i < 10; i++) {arr[i]() // 打印0-9 } // 第二個for循環(huán)里,var i重新賦值了,恰好是i

var arr = []; for (var i = 0; i < 10; i++) {arr[i] = function () {console.log(i)} } // 上個for循環(huán)var i是全局的,退出循環(huán)后為10 for (var index = 0; index < 10; index++) {arr[index]() // 10個10 }

==================================================

let是在塊中聲明的變量,每當聲明一個function都會傳入當前for的塊中單獨的i進去。也就是說let是塊變量,在自己的塊,或者子塊中使用。而不是只在函數(shù)或全局作用域中使用。立即執(zhí)行函數(shù)是為了將每次的i作為函數(shù)作用域中的局部變量傳入與外界的i隔離。

// 用let聲明,由于存在父子級作用域,相當于也形成了閉包 var arr = []; for (let i = 0; i < 10; i++) {arr[i] = function () {console.log(i)} } // 即使index用let打印的也是0-9 for (var index = 0; index < 10; index++) {arr[index]() // 0-9 } // 轉譯之后 "use strict";var arr = [];var _loop = function _loop(i) {arr[i] = function () {console.log(i);}; };for (var i = 0; i < 10; i++) {_loop(i); // 這里立即執(zhí)行了 }for (var index = 0; index < 10; index++) {arr[index](); // 0-9 }

2.4 for循環(huán)作用域

  • for循環(huán)的特別之處,就是設置循環(huán)變量的那部分是一個父作用域,而循環(huán)體內(nèi)部是一個單獨的子作用域
for (var i = 0; i < 10; i++) {let i = 'a' console.log(i) // 10個a // 循環(huán)的index i是聲明在全局的 } console.log(i) // 10 for (let i = 0; i < 10; i++) {// for循環(huán)內(nèi)的塊級作用域// for花括號內(nèi)的塊級作用域并不相同let i = 'a'console.log(i) // 10個a } for (let i = 0; i < 10; i++) {var i = 'a' // 報錯 // 因為for循環(huán)內(nèi),這里var聲明的i會提升到全局// 而for循環(huán)條件又用let聲明一次i,重復聲明了console.log(i) } if (1) {let a = 1;console.log(a) // 1{let a = 10;console.log(a) // 10} }

以前遇到的有IIFE里不用關鍵字聲明的嗎

let a = 1; (function(){a = 10; console.log(a) // 10 })() console.log(a) // 10 let a = 1; (function(){let a = 10;console.log(a) // 10 })() console.log(a) // 1 var a; (function () {a = 10;console.log(a) // 10 })(); (function () {a = 100;console.log(a) // 100 })(); console.log(a) // 100 (function () {var a = 10;console.log(a) // 10 })(); (function () {var a = 100;console.log(a) // 100 })(); console.log(a) // 報錯 // Uncaught ReferenceError: a is not defined

思考:在index.html文件的script標簽里編碼,既有es5的語法,又有es6的語法,在瀏覽器中打開時,瀏覽器會將所有代碼轉譯成es6嗎
不會轉譯,瀏覽器不同的版本對es的支持不一樣。(現(xiàn)代瀏覽器基本都支持ES6)
現(xiàn)在普遍兼容es6的語法。但對特殊的語法需要babel轉譯, 包括對象的拓展,類的修飾等等,這些是需要babel轉譯的。

塊級作用域等于匿名函數(shù)的立即調(diào)用嗎?并不,塊級作用域沒有返回值。二者本質(zhì)不同。

思考總結,在塊級作用域{}內(nèi),用let/const聲明的和父作用域同名的變量x,在轉譯ES6的時候,會被編譯成另一變量_x

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結

以上是生活随笔為你收集整理的ES6-2 块级作用域与嵌套、let、暂行性死区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。