亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

面試官常問(wèn)之說(shuō)說(shuō)js中var、let、const的區(qū)別

 更新時(shí)間:2022年03月09日 10:26:52   作者:款冬_  
var、let和const都是JavaScript中用來(lái)聲明變量的關(guān)鍵字,并且let和 const關(guān)鍵字是在 ES6 中才新增的,下面這篇文章主要給大家介紹了關(guān)于var、let、const區(qū)別的相關(guān)資料,需要的朋友可以參考下

前言

關(guān)于 var、let 和 const 三個(gè)關(guān)鍵字的區(qū)別,是一個(gè)老生常談的問(wèn)題,也是經(jīng)典的面試題。本篇文章將全面講解三者的特性,以及它們之間的區(qū)別,由淺入深讓你徹底搞懂這個(gè)知識(shí)點(diǎn)。

變量聲明

ECMAScript 變量是松散類型的,意思就是變量可以用于保存任何類型的數(shù)據(jù),每個(gè)變量只不過(guò)是一個(gè)用于保存任意值的命名占位符。

有3個(gè)關(guān)鍵字可以聲明變量:var、let和const,var在 ECMAScript 的所有版本中都可以使用,而let和const只能在 ES6 及更晚的版本中使用。

var

要定義變量,可以使用var操作符(注意 var 是一個(gè)關(guān)鍵字),后跟變量名(即標(biāo)識(shí)符,如前所述):

var message;

上面這行代碼定義了一個(gè)名為message的變量,它可以保存任何類型的值。不初始化的情況下,變量會(huì)保存一個(gè)特殊值undefined。

ECMAScript 實(shí)現(xiàn)變量初始化,因此可以同時(shí)定義變量并設(shè)置它的值:

var messgae = "hi";

message被定義為一個(gè)保存字符串值 "hi" 的變量。像這樣初始化變量不會(huì)將它標(biāo)識(shí)為字符串類型,只是一個(gè)簡(jiǎn)單的賦值而已。隨后,不僅可以改變保存的值,還可以改變值的類型:

var message = "hi";
message = 666; // 合法,但不推薦
console.log(message); // 666

如果需要定義多個(gè)變量,可以在一條語(yǔ)句中用逗號(hào)分隔每個(gè)變量(及可選的初始化):

var message,
    name = "孫悟空",
    age = 18;

作用域

使用var操作符定義的變量會(huì)成為包含它的函數(shù)的局部變量。例如,使用var在一個(gè)函數(shù)內(nèi)部定義一個(gè)變量,就意味著該變量將在函數(shù)退出時(shí)被銷毀:

function test() {
    var message = "hi"; // 局部變量
}
test();
console.log(message); // error: message is not defined

不過(guò),在函數(shù)內(nèi)部定義變量時(shí)省略var操作符,可以創(chuàng)建一個(gè)全局變量:

function test() {
    message = "hi"; // 全局變量
}
test();
console.log(message); // ok

雖然可以通過(guò)省略var操作符定義全局變量,但不推薦這么做。在嚴(yán)格模式下,如果像這樣給未聲明的變量賦值,會(huì)報(bào)錯(cuò)。

在同一個(gè)作用域內(nèi),反復(fù)多次使用var聲明同一個(gè)變量也是沒問(wèn)題的:

function test() {
    var message = "hi";
    var message = false;
    var message = 666;

    console.log(message); 
}
test(); // 666

提升

所謂的提升,就是把所有變量聲明都拉到函數(shù)作用域的頂部。注意,只提升聲明,不提升賦值操作。

舉個(gè)栗子:

function test() {
    console.log(message);
    var message = "hi";
}
test(); // undefined

上面的代碼不會(huì)報(bào)錯(cuò),因?yàn)槭褂胿ar關(guān)鍵字聲明的變量會(huì)提升到函數(shù)作用域的頂部,跟下面的代碼是等價(jià)的:

function test() {
    var message;
    console.log(message);
    message = "hi";
}
test(); // undefined

let

let 和 var 的作用差不多,但有著非常重要的區(qū)別。

作用域

var聲明的范圍是函數(shù)作用域,而let聲明的范圍是塊作用域:

if (true) {
    var message = "hi";
    console.log(message); // hi
}
console.log(message); // hi


if (true) {
    let message = "hi";
    console.log(message); // hi
}
console.log(message); // error: message is not defined

message變量之所以不能在 if 塊外部被引用,是因?yàn)樗淖饔糜騼H限于該塊內(nèi)部。塊作用域是函數(shù)作用域的子集,因此適用于var的作用域限制同樣也適用于let。

let 不允許同一個(gè)塊作用域中出現(xiàn)冗余聲明:

if (true) { 
    // error: 無(wú)法重新聲明塊范圍變量“a”
    let a;
    let a;
}

JS 引擎會(huì)記錄用于變量聲明的標(biāo)識(shí)符及其所在的塊作用域,因此嵌套使用相同的標(biāo)識(shí)符不會(huì)報(bào)錯(cuò),這是因?yàn)橥粋€(gè)塊中沒有重復(fù)聲明:

let a = 666;
console.log(a); // 666
if (true) {
    let a = '啊哈哈';
    console.log(a); // 啊哈哈
}

var和let聲明的并不是不同類型的變量,它們只是指出變量在相關(guān)作用域如何存在,所以對(duì)聲明冗余報(bào)錯(cuò)不會(huì)因混用var和let而受影響:

// error
var a;
let a;

// error
let b;
var b;

暫時(shí)性死區(qū)

let聲明的變量不會(huì)在作用域中被提升:

if (true) {
    console.log(x); // error: 在賦值前使用了變量“x”
    let x = 520;
}

在解析代碼時(shí),JS 引擎也會(huì)注意出現(xiàn)在塊后面的let聲明,只不過(guò)在此之前不能以任何方式來(lái)引用未聲明的變量。在let聲明之前的執(zhí)行瞬間被稱為暫時(shí)性死區(qū),在此階段引用任何后面才聲明的變量都會(huì)報(bào)錯(cuò)。

const

const的行為與let基本相同,唯一一個(gè)重要的區(qū)別是:用const聲明變量時(shí)必須同時(shí)初始化變量,且嘗試修改const聲明的變量會(huì)導(dǎo)致運(yùn)行時(shí)報(bào)錯(cuò):

const a; // error: 必須初始化 "const" 聲明

const b = 250;
b = 520; // error: 無(wú)法賦值給 "b" ,因?yàn)樗浅?shù)

注意,const聲明的限制只適用于它指向的變量的引用,換句話說(shuō),如果const變量引用的是一個(gè)對(duì)象,那么修改這個(gè)對(duì)象內(nèi)部的屬性并不違反const限制:

const obj = { x: 666 };
obj.x = 888; // ok
obj.y = '啊哈哈'; // ok

擴(kuò)展

全局聲明

使用var在全局作用域中聲明的變量會(huì)成為window對(duì)象的屬性,let和const聲明的變量則不會(huì):

var a = 666;
console.log(window.a); // 666

let b = 666;
console.log(window.b); // undefined

const c = 666;
console.log(window.c); // undefined

for 循環(huán)中的 let 聲明

先看個(gè)??:

for (var i = 0; i < 5; i++) {
    ...
}
console.log(i);

思考一下,打印結(jié)果會(huì)是什么?

由于var聲明的變量沒有塊作用域,所以迭代變量i會(huì)滲透到循環(huán)體外部,當(dāng)i遞增到5時(shí)退出循環(huán),打印出結(jié)果為5。

如果用let聲明迭代變量,就可以把迭代變量的作用域限制為 for 循環(huán)塊內(nèi)部:

for (let i = 0; i < 5; i++) {
    ...
}
console.log(i); // error: i is not defined

再看個(gè)栗子:

for (var i = 0; i < 5; i++) {
    setTimeout( () => {
        console.log(i);
    }, 0 )
}

你可能以為會(huì)輸出:0、1、2、3、4,實(shí)際上會(huì)輸出:5、5、5、5、5。

之所以是這樣的結(jié)果,是因?yàn)樵谕顺鲅h(huán)時(shí),迭代變量保存的是導(dǎo)致循環(huán)退出的值,也就是 5。在之后異步執(zhí)行超時(shí)邏輯時(shí),所有的i都是同一個(gè)變量,因此輸出的都是同一個(gè)最終值。

而在使用let聲明迭代變量時(shí),JS 引擎在后臺(tái)會(huì)為每個(gè)迭代循環(huán)聲明一個(gè)新的迭代變量,每個(gè) setTimeout 引用的都是不同的變量實(shí)例,所以 console.log 輸出的是我們期望的值,也就是循環(huán)執(zhí)行過(guò)程中每個(gè)迭代變量的值:

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

這是一道經(jīng)典面試題,不是很理解的話一定要多看幾遍,最好動(dòng)手實(shí)踐一下,徹底搞懂為止。

總結(jié)

  • var 聲明的范圍是函數(shù)作用域,let 和 const 聲明的范圍是塊作用域

  • var 聲明的變量會(huì)被提升到函數(shù)作用域的頂部,let 和 const 聲明的變量不存在提升,且具有暫時(shí)性死區(qū)特征

  • var 允許在同一個(gè)作用域中重復(fù)聲明同一個(gè)變量,let 和 const 不允許

  • 在全局作用域中使用 var 聲明的變量會(huì)成為 window 對(duì)象的屬性,let 和 const 聲明的變量則不會(huì)

  • const 的行為與 let 基本相同,唯一一個(gè)重要的區(qū)別是,使用 const 聲明的變量必須進(jìn)行初始化,且不能被修改

聲明風(fēng)格及最佳實(shí)踐

ECMAScript 6 增加 let 和 const 從客觀上為這門語(yǔ)言更精確地聲明作用域和語(yǔ)義提供了更好的支持,行為怪異的 var 所造成的問(wèn)題,已經(jīng)讓 JS 社區(qū)為之苦惱了很多年。隨著這兩個(gè)關(guān)鍵字的出現(xiàn),新的有助于提升代碼質(zhì)量的最佳實(shí)踐方式也逐漸顯現(xiàn)。

var 已經(jīng)被時(shí)代所拋棄,不建議再使用。限制自己只使用 let 和 const 有助于提升代碼質(zhì)量,因?yàn)樽兞坑辛嗣鞔_的作用域、聲明位置以及不變的值。

優(yōu)先使用 const,let 次之。使用 const 聲明可以讓瀏覽器運(yùn)行時(shí)強(qiáng)制保持變量不變,也可以讓靜態(tài)代碼分析工具提前發(fā)現(xiàn)不合法的賦值操作。只在提前知道未來(lái)會(huì)有修改時(shí),才使用 let。這樣可以讓開發(fā)者更有信心地推斷某些變量的值永遠(yuǎn)不會(huì)變,同時(shí)也能迅速發(fā)現(xiàn)因意外賦值導(dǎo)致的非預(yù)期行為。

到此這篇關(guān)于ja中var、let、const區(qū)別的文章就介紹到這了,更多相關(guān)var、let、const區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論