第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開(kāi)發(fā)者教程

ES6-10 入門(mén)教程

ES6+ let

1. 前言

本節(jié)我們一起學(xué)習(xí)下 ES6 中的 let,在 ES5 中變量的方法只有一個(gè) var ,但是使用 var 來(lái)定義的變量存在很多缺陷和弊端,ES6 引入了 let 語(yǔ)句來(lái)聲明變量,同時(shí)引入了很多概念,比如塊級(jí)作用域、暫存死區(qū)等等。限制了任意聲明變量,提升了程序的健壯性。

2. 基本用法

let 的使用方法類(lèi)似于 var,并可以代替 var 來(lái)聲明變量。

{
  let name = 'imooc';
}

let 允許你聲明一個(gè)作用域被限制在塊級(jí)中的變量、語(yǔ)句或者表達(dá)式。與 var 關(guān)鍵字不同的是,var 聲明的變量只能在全局或者整個(gè)函數(shù)塊中。 varlet 的不同之處在于 let 是在編譯時(shí)才初始化,也就是在同一個(gè)塊級(jí)下不能重復(fù)地聲明一個(gè)變量,否則會(huì)報(bào)錯(cuò)。

let 不會(huì)在全局聲明時(shí)創(chuàng)建 window 對(duì)象的屬性,但是 var 會(huì)。

{
  var name = 'imooc'  // imooc
  var name = 'iimooc' // iimooc 
}
console.log(window.name)	// iimooc
{
  let age = 10        // 10
  let age = 18        // Uncaught SyntaxError: Identifier 'age' has already been declared 
}
console.log(window.age)		// undefined

上面的代碼中,在一個(gè)塊中分別使用 varlet 來(lái)聲明變量對(duì)比他們之間的差異,從上面的代碼操作可以看出,我們可以使用 var 多次對(duì) name 聲明,但是使用 let 聲明的 age,后面再使用 let 對(duì)其聲明是會(huì)報(bào)錯(cuò)的。
var 是沒(méi)有塊的概念的,聲明的變量會(huì)是 window 對(duì)象上的屬性,在最外層的 window 上可以取到。而 let 存在塊的概念,不會(huì)添加到 window 對(duì)象上,這些是 let 和 var 之間的區(qū)別。從這里我們可以了解到為什么使用 let。

3. 塊級(jí)作用域

在深入了解 let 前,我們需要了解一下,在 JavaScript 中有哪些作用域:

  1. 全局作用域
  2. 函數(shù)作用域 / 局部作用域
  3. 塊級(jí)作用域

上面是 JavaScript 中的三種作用域,那什么是作用域呢?首先要明白的是:幾乎所有的編程語(yǔ)言都存在在變量中儲(chǔ)值的能力,存儲(chǔ)完就需要使用這些值。所以,作用域就是一套規(guī)則,按照這套規(guī)則可以方便地去存儲(chǔ)和訪問(wèn)變量。

在 ES5 中的作用域有全局作用域和函數(shù)作用域,而塊級(jí)作用域是 ES6 的概念。

3.1 全局作用域

全局作用域顧名思義,就是在任何地方都能訪問(wèn)到它,在瀏覽器中能通過(guò) window 對(duì)象拿到的變量就是全局作用域下聲明的變量。

var name = 'imooc';
console.log(window.name)   // imooc

使用 var 定義的變量,可以在 window 對(duì)象上拿到此變量。這里的 name 就是全局作用域下的變量。

3.2 函數(shù)作用域

函數(shù)作用域就是在函數(shù)內(nèi)部定義的變量,也就是局部作用域,在函數(shù)的外部是不能使用這個(gè)變量的,也就是對(duì)外是封閉的,從外層是無(wú)法直接訪問(wèn)函數(shù)內(nèi)部的作用域的。

function bar() {
  var name = 'imooc';
}
console.log(name);  // undefined

在函數(shù)內(nèi)部定義的 name 變量,在函數(shù)外部是訪問(wèn)不了的。要想在函數(shù)外部訪問(wèn)函數(shù)內(nèi)部的變量可以通過(guò) return 的方式返回出來(lái)。

function bar(value) {
  var name = ' imooc';
  return value + name;
}
console.log(bar('hello'));  // hello imooc

借助 return 執(zhí)行函數(shù) bar 可以取到函數(shù)內(nèi)部的變量 name 的值進(jìn)行使用。

3.3 塊級(jí)作用域

塊級(jí)作用域是 ES6 的概念,它的產(chǎn)生是要有一定的條件的,在大括號(hào)({})中,使用 letconst 聲明的變量,才會(huì)產(chǎn)生塊級(jí)作用域。
這里需要注意的是,塊級(jí)作用域的產(chǎn)生是 letconst 帶來(lái)的,而不是大括號(hào),大括號(hào)的作用是限制 letconst 的作用域范圍。當(dāng)不在大括號(hào)中聲明時(shí), letconst 的作用域范圍是全局。

let name = 10;
console.log(window.name)   // undefined

上面的代碼可以看到,使用 let 方式聲明的變量在 window 下是取不到的。

var num = 10;
{
  var num = 20;
  console.log(num)  // 20
}
console.log(num)    // 20

在使用 var 聲明的情況下,可以看出,外層的 num 會(huì)被 {} 中的 num 覆蓋,所以沒(méi)有塊級(jí)作用域的概念,下面看下使用 let 方式聲明:

let num = 10;
{
  console.log(num); // Uncaught ReferenceError: Cannot access 'num' before initialization
  let num = 20;
  console.log(num)  // 20
}
console.log(num)    // 10

這里可以看出 {} 內(nèi)外是互不干涉和影響的,如果在聲明 num 的前面進(jìn)行打印的話,還會(huì)報(bào)錯(cuò),這個(gè)時(shí)候,num 處于暫存死區(qū),是不能被使用的,下面我們會(huì)具體說(shuō)明。

在低版本瀏覽器中不支持 ES6 語(yǔ)法,通常需要把 ES6 語(yǔ)法轉(zhuǎn)換成 ES5,使用 babel 把上面的代碼轉(zhuǎn)換后得到如下結(jié)果:

var num = 10;
{
  console.log(_num); // num is not defined
  var _num = 20;
  console.log(_num); // 20
}
console.log(num);    // 10

從上面的代碼中可以看出,雖然在 ES6 語(yǔ)法使用的是相同的變量名字,但是底層 JS 進(jìn)行編譯時(shí)會(huì)認(rèn)為他們是不同的變量。也就是說(shuō)即使大括號(hào)中聲明的變量和外面的變量是相同的名字,但是在編譯過(guò)程它們是沒(méi)有關(guān)系的。

塊級(jí)作用域可以任意嵌套,如下實(shí)例:

{{
  let x = 'Hello imooc'
  {
    console.log(x); // Hello imooc
    let y = 'Hello World'
  }
  console.log(y);   // 引用錯(cuò)誤 ReferenceError: y is not defined.
}};

上方代碼每一層都是一個(gè)單獨(dú)的作用域,內(nèi)層作用域可以讀取外層的變量,所以第一個(gè)會(huì)打印 Hello imooc, 而外層無(wú)法讀取內(nèi)層的變量,所以會(huì)報(bào)錯(cuò)。

4. 不能變量提升

對(duì)應(yīng) var 我們知道可以變量提升的,提升到作用域的最頂部,作用域是全局,使得聲明變量前也可以使用,但值為 undefined。

{
  console.log(bar); // 輸出undefined,沒(méi)有值但不會(huì)報(bào)錯(cuò)
  var bar = 1;
}

一般變量都應(yīng)該先聲明再使用,所以 letconst 語(yǔ)法規(guī)定必須聲明后使用,否則報(bào)錯(cuò)。

{
  console.log(name); // 引用錯(cuò)誤 ReferenceError: name is not defined.
  let name = 'imooc';
}

上面代碼中,都是在聲明前的時(shí)候使用變量的,這時(shí)候由于 let 不能進(jìn)行變量提升所以會(huì)報(bào)引用錯(cuò)誤。

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

上面講到在變量聲明前使用這個(gè)變量,就會(huì)報(bào)錯(cuò)。在代碼塊內(nèi),使用 let 命令聲明變量之前,該變量都是不可用的。這在語(yǔ)法上,稱(chēng)為 “暫時(shí)性死區(qū)”(temporal dead zone,簡(jiǎn)稱(chēng) TDZ)。

{
  console.log(name);  // ReferenceError: name is not defined. 
  let name = 'imooc';
  console.log(name);  // imooc
}

上面代碼中,在塊中使用了 let 聲明了 name 變量,在使用前對(duì) name 進(jìn)行了聲明,name 則會(huì)處于暫存死區(qū),不能被使用,如果引用則會(huì)引用錯(cuò)誤。

Tips:注意對(duì)于 typeof 也是會(huì)報(bào)錯(cuò)的。

{
  console.log(typeof name);  // Uncaught ReferenceError: Cannot access 'name' before initialization
  let name = 'imooc';
}

上面的代碼中,name 引用錯(cuò)誤:無(wú)法在初始化之前訪問(wèn) name,因?yàn)?name 在這個(gè)塊的下面進(jìn)行了聲明,name 就是一個(gè)死區(qū),不能被引用了。因此,typeof 運(yùn)行時(shí)就會(huì)拋出一個(gè) ReferenceError 的參數(shù)錯(cuò)誤。

6. 重復(fù)聲明報(bào)錯(cuò)

let 不允許在同一個(gè)函數(shù)或塊作用域中重復(fù)聲明同一個(gè)變量,否則會(huì)引起語(yǔ)法錯(cuò)誤(SyntaxError)。

{
  let x = 10;
  let x = 11;
}
// Uncaught SyntaxError: Identifier 'x' has already been declared

在上面的代碼中報(bào)錯(cuò),所以,同一個(gè)變量名不可以在同一個(gè)作用域內(nèi)重復(fù)聲明。

{
  let x = 10;
  var x = 1;
}

即使使用 var 去聲明也是不可以的,我們知道當(dāng)使用 let 聲明的時(shí)候 x 已經(jīng)是一個(gè)死區(qū)了,不可以被重復(fù)聲明了。

Tips:注意在 switch 語(yǔ)句中只有一個(gè)塊級(jí)作用域,所以下面這種情況也是會(huì)報(bào)錯(cuò)的。

let x = 1;
switch(x) {
  case 0:
    let num;
    break;
    
  case 1:
    let num;//重復(fù)聲明了
    break;
}
// 報(bào)錯(cuò)

如果把 case 后面的語(yǔ)句放到塊作用域中則不會(huì)報(bào)錯(cuò)。

let x = 1;
switch(x) {
  case 0: {//塊
    let num;
    break;
  } 
  case 1: {//塊
    let num;//這里就沒(méi)有關(guān)系了,可以正常聲明
    break;
  }
}

上方代碼,case 后面的語(yǔ)句 let 變量聲明在放到塊中,是單獨(dú)的作用域,所以就不會(huì)報(bào)錯(cuò)。

7. 小結(jié)

本節(jié)講解了 let 語(yǔ)句的使用,還有作用域的概念,需要注意以下幾點(diǎn):

  1. let 只作用于塊級(jí)作用域內(nèi);
  2. let 聲明的變量不能進(jìn)行變量提升,存在暫存死區(qū);
  3. let 聲明的變量不允許重復(fù)聲明,無(wú)論重復(fù)用 var 或者其他聲明都不行;
  4. 盡量使用 let 去代替 var 來(lái)聲明變量。