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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

var、let、const的区别

發布時間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 var、let、const的区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

var 關鍵詞

1. var聲明作用域

var定義的變量,沒有塊的概念,可以跨塊訪問, 不能跨函數訪問

function test() {var message = "hello world"; // 局部變量 } test(); console.log(message); // 報錯

函數test()調用時會創建變量message并給它賦值,調用之后變量隨即被銷毀。因此,在函數test()之外調用變量message會報錯

在函數內定義變量時省略var操作符,可以創建一個全局變量

function test() {message = "hello world"; // 局部變量 } test(); console.log(message); // hello world

省略掉var操作符之后,message就變成了全局變量。只要調用一次函數test(),就會定義這個變量,并且可以在函數外部訪問到。在局部作用域中定義的全局變量很難維護,不推薦這么做。在嚴格模式下,如果像這樣給未聲明的變量賦值,則會導致拋出ReferenceError。

2. var聲明提升

var在js中是支持預解析的,如下代碼不會報錯。這是因為使用var聲明的變量會自動提升到函數作用域頂部:

function foo() {console.log(age);var age = 26; } foo(); // undefined

javaScript引擎,在代碼預編譯時,javaScript引擎會自動將所有代碼里面的var關鍵字聲明的語句都會提升到當前作用域的頂端,如下代碼:

function foo() {var age;console.log(age);age = 26; } foo(); // undefined

let聲明

1. let聲明作用域

let定義的變量,只能在塊作用域里訪問,不能跨塊訪問,也不能跨函數訪問,而var可以跨塊訪問

// var定義的變量 if (true) {var name = 'Matt';console.log(name); // Matt } console.log(name); // Matt// let定義的變量 if (true) {let age = 26;console.log(age); // 26 } console.log(age); // ReferenceError: age沒有定義

let也不允許同一個塊作用域中出現冗余聲明(重復聲明)

var name; var name;let age; let age; // SyntaxError;標識符age已經聲明過了

2. 暫時性死區

let、const與var的另一個重要的區別,let、const聲明的變量不會在作用域中被提升。ES6新增的let、const關鍵字聲明的變量會產生塊級作用域,如果變量在當前作用域中被創建出來,由于此時還未完成語法綁定,所以是不能被訪問的,如果訪問就會拋出錯誤ReferenceError。因此,在這運行流程進入作用域創建變量,到變量可以被訪問之間的這一段時間,就稱之為暫時死區。

// name會被提升 console.log(name); // undefined var name = 'Matt';// age不會被提升 console.log(age); // ReferenceError:age沒有定義 let age = 26;

3. 全局聲明

與var關鍵字不同,var定義的全局變量會掛載到window對象上,使用window可以訪問,而let在全局作用域中聲明的變量不會成為window對象的屬性

var name = 'Matt'; console.log(window.name); // 'Matt'let age = 26; console.log(window.age); // undefined

4. for循環中的var、let聲明

for循環中var定義的迭代變量會滲透到循環體外部:

for (var i = 0; i < 5; ++i) {// 循環邏輯 } console.log(i); // 5

改成使用let之后,這個問題就消失了,因為迭代變量的作用域僅限于for循環塊內部:

for (let i = 0; i < 5; ++i) {// 循環邏輯 } console.log(i); // ReferenceError: i沒有定義

使用var和let定義for循環中的變量,循環里使用定時器setTimeout后循環結果如下代碼:

for (var i = 0; i < 5; ++i) {setTimeout(() => console.log(i), 0) } // 輸出5、5、5、5、5for (let i = 0; i < 5; ++i) {setTimeout(() => console.log(i), 0) } // 輸出0、1、2、3、4

let 是在代碼塊內有效,var 是在全局范圍內有效。let 只能聲明一次 ,var 可以聲明多次。

當同步代碼執行完畢后,開始執行異步的setTimeout代碼,執行setTimeout時需要從當前作用域內尋找一個變量 i,for循環執行完畢,當前 i=5,執行setTimeout時輸出為5,任務隊列中的剩余4個setTimeout也依次執行,輸出為5。

變量 j 是用 let 聲明的,當前的 i 只在本輪循環中有效,每次循環的 j 其實都是一個新的變量,所以 setTimeout 定時器里面的 j 其實是不同的變量,即最后輸出0-4。

const聲明

const的行為與let基本相同,唯一一個重要的區別是:

const是用來定義常量的,而且定義的時候必須賦值,不賦值會報錯,定義之后是不允許被修改的,修改const聲明的變量會導致運行時錯誤。

const age = 26; age = 36; // TypeError: 給常量賦值// const也不允許重復聲明 const name = 'Matt'; const name = 'Nicholas'; // SyntaxError// const聲明的作用域也是塊 const name = 'Matt'; if (true) {const name = 'Nicholas'; } console.log(name); // Matt

而const聲明的變量是一個對象時,修改這個對象內部的屬性并不會報錯。

這是因為const聲明的是棧區里的內容不能修改,基本數據類型的值直接在棧內存中存儲,而引用數據類型在棧區保存的是對象在堆區的地址,修改對象的屬性,不會修改對象在棧區的地址,如果重新給對象person賦值,則會報錯。

const person = {name: 'Lili' }; person.name = 'Matt'; // ok

JavaScript引擎會為for循環中的let聲明分別創建獨立的變量實例,雖然const變量跟let變量很相似,但是不能用const來聲明迭代變量(因為迭代變量會自增):

for (const i = 0; i < 10; ++i) {} // TypeError:給常量賦值

不過,如果你只想用const聲明一個不會被修改的for循環變量,那也是可以的。也就是說,每次迭代只是創建一個新變量。這對for-of和for-in循環特別有意義:

let i = 0; for (const j = 7; i < 5; ++i) {console.log(j); } // 7, 7, 7, 7, 7 for (const key in {a: 1, b: 2}) {console.log(key); } // a, b for (const value of [1,2,3,4,5]) {console.log(value); } // 1, 2, 3, 4, 5

以上內容結合《JavaScript高級程序設計(第4版)》以及自己理解所寫,歡迎大家一起來討論。

總結

以上是生活随笔為你收集整理的var、let、const的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

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