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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

“睡服”面试官系列第一篇之let和const命令(建议收藏学习)

發(fā)布時間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “睡服”面试官系列第一篇之let和const命令(建议收藏学习) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

1let命令

1.1基本用法

1.2for循環(huán)小案例

1.3不存在變量提升

1.4暫時性死區(qū)

1.5不允許重復聲明

2塊級作用域

2.1為什么需要塊級作用域?

2.2ES6 的塊級作用域

2.3塊級作用域和函數(shù)聲明

3const

3.1本質(zhì)

4頂層對象的屬性

5global對象

6總結


1let命令

1.1基本用法

ES6 新增了 let 命令,用來聲明變量。它的用法類似于 var ,但是所聲明的變量,只在 let 命令所在的代碼塊內(nèi)有效。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>{let a = 10;var b = 1}console.log(a) // ReferenceError: a is not defined.console.log(b) //1</script> </body></html>

上面代碼在代碼塊之中,分別用 let 和 var 聲明了兩個變量。然后在代碼塊之外調(diào)用這兩個變量,結果 let 聲明的變量報錯, var 聲明的變量返回了正確
的值。這表明, let 聲明的變量只在它所在的代碼塊有效

1.2for循環(huán)小案例

for 循環(huán)的計數(shù)器,就很合適使用 let 命令

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>for (let i = 0; i < 10; i++) {// ...}console.log(i);// ReferenceError: i is not defined</script> </body></html>

上面代碼中,計數(shù)器 i 只在 for 循環(huán)體內(nèi)有效,在循環(huán)體外引用就會報錯。

下面的代碼如果使用 var ,最后輸出的是 10 。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>var a = [];for (var i = 0; i < 10; i++) {a[i] = function() {console.log(i);};}a[6](); // 10</script> </body></html>

上面代碼中,變量 i 是 var 命令聲明的,在全局范圍內(nèi)都有效,所以全局只有一個變量 i 。每一次循環(huán),變量 i 的值都會發(fā)生改變,而循環(huán)內(nèi)被賦給數(shù)組 a
的函數(shù)內(nèi)部的 console.log(i) ,里面的 i 指向的就是全局的 i 。也就是說,所有數(shù)組 a 的成員里面的 i ,指向的都是同一個 i ,導致運行時輸出的是最后
一輪的 i 的值,也就是 10。
如果使用 let ,聲明的變量僅在塊級作用域內(nèi)有效,最后輸出的是 6

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>var a = [];for (let i = 0; i < 10; i++) {a[i] = function() {console.log(i);};}a[6](); // 10</script> </body></html>

上面代碼中,變量 i 是 let 聲明的,當前的 i 只在本輪循環(huán)有效,所以每一次循環(huán)的 i 其實都是一個新的變量,所以最后輸出的是 6 。你可能會問,如果每
一輪循環(huán)的變量 i 都是重新聲明的,那它怎么知道上一輪循環(huán)的值,從而計算出本輪循環(huán)的值?這是因為 JavaScript 引擎內(nèi)部會記住上一輪循環(huán)的值,初
始化本輪的變量 i 時,就在上一輪循環(huán)的基礎上進行計算。
另外, for 循環(huán)還有一個特別之處,就是設置循環(huán)變量的那部分是一個父作用域,而循環(huán)體內(nèi)部是一個單獨的子作用域。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>for (let i = 0; i < 3; i++) {let i = 'abc';console.log(i);}// abc// abc// abc</script> </body></html>

上面代碼正確運行,輸出了 3 次 abc 。這表明函數(shù)內(nèi)部的變量 i 與循環(huán)變量 i 不在同一個作用域,有各自單獨的作用域。

1.3不存在變量提升

var 命令會發(fā)生”變量提升“現(xiàn)象,即變量可以在聲明之前使用,值為 undefined 。這種現(xiàn)象多多少少是有些奇怪的,按照一般的邏輯,變量應該在聲明語
句之后才可以使用。
為了糾正這種現(xiàn)象, let 命令改變了語法行為,它所聲明的變量一定要在聲明后使用,否則報錯

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// var 的情況console.log(foo); // 輸出undefinedvar foo = 2;// let 的情況console.log(bar); // 報錯ReferenceErrorlet bar = 2</script> </body></html>

上面代碼中,變量 foo 用 var 命令聲明,會發(fā)生變量提升,即腳本開始運行時,變量 foo 已經(jīng)存在了,但是沒有值,所以會輸出 undefined 。變量 bar 用
let 命令聲明,不會發(fā)生變量提升。這表示在聲明它之前,變量 bar 是不存在的,這時如果用到它,就會拋出一個錯誤。

1.4暫時性死區(qū)

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

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>var tmp = 123;if (true) {tmp = 'abc'; // ReferenceErrorlet tmp;}</script> </body></html>

上面代碼中,存在全局變量 tmp ,但是塊級作用域內(nèi) let 又聲明了一個局部變量 tmp ,導致后者綁定這個塊級作用域,所以在 let 聲明變量前,對 tmp 賦
值會報錯。
ES6 明確規(guī)定,如果區(qū)塊中存在 let 和 const 命令,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,
就會報錯。
總之,在代碼塊內(nèi),使用 let 命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區(qū)”(temporal dead zone,簡稱 TDZ)。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>if (true) {// TDZ開始tmp = 'abc'; // ReferenceErrorconsole.log(tmp); // ReferenceErrorlet tmp; // TDZ結束console.log(tmp); // undefinedtmp = 123;console.log(tmp); // 123}</script> </body></html>

上面代碼中,在 let 命令聲明變量 tmp 之前,都屬于變量 tmp 的“死區(qū)”。
“暫時性死區(qū)”也意味著 typeof 不再是一個百分之百安全的操作

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>typeof x; // ReferenceErrorlet x;</script> </body></html>

上面代碼中,變量 x 使用 let 命令聲明,所以在聲明之前,都屬于 x 的“死區(qū)”,只要用到該變量就會報錯。因此, typeof 運行時就會拋出一個
ReferenceError 。
作為比較,如果一個變量根本沒有被聲明,使用 typeof 反而不會報錯

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>typeof undeclared_variable // "undefined"</script> </body></html>

上面代碼中, undeclared_variable 是一個不存在的變量名,結果返回“undefined”。所以,在沒有 let 之前, typeof 運算符是百分之百安全的,永遠不
會報錯。現(xiàn)在這一點不成立了。這樣的設計是為了讓大家養(yǎng)成良好的編程習慣,變量一定要在聲明之后使用,否則就報錯。
有些“死區(qū)”比較隱蔽,不太容易發(fā)現(xiàn)

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>function bar(x = y, y = 2) {return [x, y];}bar(); // 報錯</script> </body></html>

上面代碼中,調(diào)用 bar 函數(shù)之所以報錯(某些實現(xiàn)可能不報錯),是因為參數(shù) x 默認值等于另一個參數(shù) y ,而此時 y 還沒有聲明,屬于”死區(qū)“。如果 y 的默
認值是 x ,就不會報錯,因為此時 x 已經(jīng)聲明了。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>function bar(x = 2, y = x) {return [x, y];}bar(); // [2, 2]</script> </body></html>

另外,下面的代碼也會報錯,與 var 的行為不同

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 不報錯var x = x;// 報錯let x = x;// ReferenceError: x is not defined</script> </body></html>

上面代碼報錯,也是因為暫時性死區(qū)。使用 let 聲明變量時,只要變量在還沒有聲明完成前使用,就會報錯。上面這行就屬于這個情況,在變量 x 的聲明
語句還沒有執(zhí)行完成前,就去取 x 的值,導致報錯”x 未定義“。
ES6 規(guī)定暫時性死區(qū)和 let 、 const 語句不出現(xiàn)變量提升,主要是為了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行為。
這樣的錯誤在 ES5 是很常見的,現(xiàn)在有了這種規(guī)定,避免此類錯誤就很容易了。
總之,暫時性死區(qū)的本質(zhì)就是,只要一進入當前作用域,所要使用的變量就已經(jīng)存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲
取和使用該變量。

1.5不允許重復聲明

let 不允許在相同作用域內(nèi),重復聲明同一個變量

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 報錯function func() {let a = 10;var a = 1;}// 報錯function func() {let a = 10;let a = 1;}</script> </body></html>

因此,不能在函數(shù)內(nèi)部重新聲明參數(shù)

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>function func(arg) {let arg; // 報錯}function func(arg) {{let arg; // 不報錯}}</script> </body></html>

2塊級作用域

2.1為什么需要塊級作用域?

ES5 只有全局作用域和函數(shù)作用域,沒有塊級作用域,這帶來很多不合理的場景。
第一種場景,內(nèi)層變量可能會覆蓋外層變量。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>var tmp = new Date();function f() {console.log(tmp);if (false) {var tmp = 'hello world';}}f(); // undefined</script> </body></html>

上面代碼的原意是, if 代碼塊的外部使用外層的 tmp 變量,內(nèi)部使用內(nèi)層的 tmp 變量。但是,函數(shù) f 執(zhí)行后,輸出結果為 undefined ,原因在于變量提
升,導致內(nèi)層的 tmp 變量覆蓋了外層的 tmp 變量。
第二種場景,用來計數(shù)的循環(huán)變量泄露為全局變量

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>var s = 'hello';for (var i = 0; i < s.length; i++) {console.log(s[i]);}console.log(i); // 5</script> </body></html>

上面代碼中,變量 i 只用來控制循環(huán),但是循環(huán)結束后,它并沒有消失,泄露成了全局變量。

2.2ES6 的塊級作用域

let 實際上為 JavaScript 新增了塊級作用域。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>function f1() {let n = 5;if (true) {let n = 10;}console.log(n); // 5}</script> </body></html>

上面的函數(shù)有兩個代碼塊,都聲明了變量 n ,運行后輸出 5。這表示外層代碼塊不受內(nèi)層代碼塊的影響。如果兩次都使用 var 定義變量 n ,最后輸出的值
才是 10。
ES6 允許塊級作用域的任意嵌套。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>{{{{{let insane = 'Hello World'}}}}};</script> </body></html>

上面代碼使用了一個五層的塊級作用域。外層作用域無法讀取內(nèi)層作用域的變量。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>{{{{{let insane = 'Hello World'}console.log(insane); // 報錯}}}};</script> </body></html>

內(nèi)層作用域可以定義外層作用域的同名變量。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>{{{{let insane = 'Hello World'; {let insane = 'Hello World'}}}}};</script> </body></html>

塊級作用域的出現(xiàn),實際上使得獲得廣泛應用的立即執(zhí)行函數(shù)表達式(IIFE)不再必要了。

// IIFE 寫法(function() {var tmp = ...;...}());// 塊級作用域?qū)懛▄let tmp = ...;...}

2.3塊級作用域和函數(shù)聲明

函數(shù)能不能在塊級作用域之中聲明?這是一個相當令人混淆的問題。
ES5 規(guī)定,函數(shù)只能在頂層作用域和函數(shù)作用域之中聲明,不能在塊級作用域聲明。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 情況一if (true) {function f() {}}// 情況二try {function f() {}} catch (e) {// ...}</script> </body></html>

上面兩種函數(shù)聲明,根據(jù) ES5 的規(guī)定都是非法的。
但是,瀏覽器沒有遵守這個規(guī)定,為了兼容以前的舊代碼,還是支持在塊級作用域之中聲明函數(shù),因此上面兩種情況實際都能運行,不會報錯。ES6 引入了塊級作用域,明確允許在塊級作用域之中聲明函數(shù)。ES6 規(guī)定,塊級作用域之中,函數(shù)聲明語句的行為類似于 let ,在塊級作用域之外不可引

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>function f() {console.log('I am outside!');}(function() {if (false) {// 重復聲明一次函數(shù)ffunction f() {console.log('I am inside!');}}f();}());</script> </body></html>


上面代碼在 ES5 中運行,會得到“I am inside!”,因為在 if 內(nèi)聲明的函數(shù) f 會被提升到函數(shù)頭部,實際運行的代碼如下。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// ES5 環(huán)境function f() {console.log('I am outside!');}(function() {function f() {console.log('I am inside!');}if (false) {}f();}());</script> </body></html>

ES6 就完全不一樣了,理論上會得到“I am outside!”。因為塊級作用域內(nèi)聲明的函數(shù)類似于 let ,對作用域之外沒有影響。但是,如果你真的在 ES6 瀏
覽器中運行一下上面的代碼,是會報錯的,這是為什么呢?
原來,如果改變了塊級作用域內(nèi)聲明的函數(shù)的處理規(guī)則,顯然會對老代碼產(chǎn)生很大影響。為了減輕因此產(chǎn)生的不兼容問題,ES6 在附錄 B里面規(guī)定,瀏覽
器的實現(xiàn)可以不遵守上面的規(guī)定,有自己的行為方式。
允許在塊級作用域內(nèi)聲明函數(shù)。
函數(shù)聲明類似于 var ,即會提升到全局作用域或函數(shù)作用域的頭部。
同時,函數(shù)聲明還會提升到所在的塊級作用域的頭部。
注意,上面三條規(guī)則只對 ES6 的瀏覽器實現(xiàn)有效,其他環(huán)境的實現(xiàn)不用遵守,還是將塊級作用域的函數(shù)聲明當作 let 處理。
根據(jù)這三條規(guī)則,在瀏覽器的 ES6 環(huán)境中,塊級作用域內(nèi)聲明的函數(shù),行為類似于 var 聲明的變量

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 瀏覽器的 ES6 環(huán)境function f() {console.log('I am outside!');}(function() {if (false) {// 重復聲明一次函數(shù)ffunction f() {console.log('I am inside!');}}f();}());// Uncaught TypeError: f is not a function</script> </body></html>

上面的代碼在符合 ES6 的瀏覽器中,都會報錯,因為實際運行的是下面的代碼。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 瀏覽器的 ES6 環(huán)境function f() {console.log('I am outside!');}(function() {var f = undefined;if (false) {function f() {console.log('I am inside!');}}f();}());// Uncaught TypeError: f is not a function</script> </body></html>

考慮到環(huán)境導致的行為差異太大,應該避免在塊級作用域內(nèi)聲明函數(shù)。如果確實需要,也應該寫成函數(shù)表達式,而不是函數(shù)聲明語句。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 函數(shù)聲明語句{let a = 'secret';function f() {return a;}}// 函數(shù)表達式{let a = 'secret';let f = function() {return a;};}</script> </body></html>

另外,還有一個需要注意的地方。ES6 的塊級作用域允許聲明函數(shù)的規(guī)則,只在使用大括號的情況下成立,如果沒有使用大括號,就會報錯

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>// 不報錯'use strict';if (true) {function f() {}}// 報錯'use strict';if (true)function f() {</script> </body></html>

3const

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

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>const PI = 3.1415;PI // 3.1415PI = 3;// TypeError: Assignment to constant variable</script> </body></html>

上面代碼表明改變常量的值會報錯。
const 聲明的變量不得改變值,這意味著, const 一旦聲明變量,就必須立即初始化,不能留到以后賦值。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>const foo;// SyntaxError: Missing initializer in const declaration</script> </body></html>

上面代碼表示,對于 const 來說,只聲明不賦值,就會報錯。
const 的作用域與 let 命令相同:只在聲明所在的塊級作用域內(nèi)有效。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>if (true) {const MAX = 5;}MAX // Uncaught ReferenceError: MAX is not defined</script> </body></html>

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

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>if (true) {console.log(MAX); // ReferenceErrorconst MAX = 5;}</script> </body></html>

上面代碼在常量 MAX 聲明之前就調(diào)用,結果報錯。
const 聲明的常量,也與 let 一樣不可重復聲明。

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>var message = "Hello!";let age = 25;// 以下兩行都會報錯const message = "Goodbye!";const age = 30</script> </body></html>

3.1本質(zhì)

const 實際上保證的,并不是變量的值不得改動,而是變量指向的那個內(nèi)存地址不得改動。對于簡單類型的數(shù)據(jù)(數(shù)值、字符串、布爾值),值就保存在
變量指向的那個內(nèi)存地址,因此等同于常量。但對于復合類型的數(shù)據(jù)(主要是對象和數(shù)組),變量指向的內(nèi)存地址,保存的只是一個指針, const 只能保
證這個指針是固定的,至于它指向的數(shù)據(jù)結構是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>const foo = {};// 為 foo 添加一個屬性,可以成功foo.prop = 123;foo.prop // 123// 將 foo 指向另一個對象,就會報錯foo = {}; // TypeError: "foo" is read-only</script> </body></html>

上面代碼中,常量 foo 儲存的是一個地址,這個地址指向一個對象。不可變的只是這個地址,即不能把 foo 指向另一個地址,但對象本身是可變的,所以
依然可以為其添加新屬性

4頂層對象的屬性

頂層對象,在瀏覽器環(huán)境指的是 window 對象,在 Node 指的是 global 對象。ES5 之中,頂層對象的屬性與全局變量是等價的

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>test</title> </head><body><script>window.a = 1;a // 1a = 2;window.a // 2</script> </body></html>

?上面代碼中,頂層對象的屬性賦值與全局變量的賦值,是同一件事。
頂層對象的屬性與全局變量掛鉤,被認為是 JavaScript 語言最大的設計敗筆之一。這樣的設計帶來了幾個很大的問題,首先是沒法在編譯時就報出變量未
聲明的錯誤,只有運行時才能知道(因為全局變量可能是頂層對象的屬性創(chuàng)造的,而屬性的創(chuàng)造是動態(tài)的);其次,程序員很容易不知不覺地就創(chuàng)建了全
局變量(比如打字出錯);最后,頂層對象的屬性是到處可以讀寫的,這非常不利于模塊化編程。另一方面, window 對象有實體含義,指的是瀏覽器的窗
口對象,頂層對象是一個有實體含義的對象,也是不合適的。

5global對象

ES5 的頂層對象,本身也是一個問題,因為它在各種實現(xiàn)里面是不統(tǒng)一的。
瀏覽器里面,頂層對象是 window ,但 Node 和 Web Worker 沒有 window 。
瀏覽器和 Web Worker 里面, self 也指向頂層對象,但是 Node 沒有 self 。
Node 里面,頂層對象是 global ,但其他環(huán)境都不支持。
同一段代碼為了能夠在各種環(huán)境,都能取到頂層對象,現(xiàn)在一般是使用 this 變量,但是有局限性。
全局環(huán)境中, this 會返回頂層對象。但是,Node 模塊和 ES6 模塊中, this 返回的是當前模塊。
函數(shù)里面的 this ,如果函數(shù)不是作為對象的方法運行,而是單純作為函數(shù)運行, this 會指向頂層對象。但是,嚴格模式下,這時 this 會返回
undefined 。
不管是嚴格模式,還是普通模式, new Function('return this')() ,總是會返回全局對象。但是,如果瀏覽器用了 CSP(Content Security
Policy,內(nèi)容安全政策),那么 eval 、 new Function 這些方法都可能無法使用。
綜上所述,很難找到一種方法,可以在所有情況下,都取到頂層對象

6總結

本博客源于本人閱讀相關書籍和視頻總結,創(chuàng)作不易,謝謝點贊支持。學到就是賺到。我是歌謠,勵志成為一名優(yōu)秀的技術革新人員。

歡迎私信交流,一起學習,一起成長。

推薦鏈接 其他文件目錄參照

“睡服“面試官系列之各系列目錄匯總(建議學習收藏)

總結

以上是生活随笔為你收集整理的“睡服”面试官系列第一篇之let和const命令(建议收藏学习)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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