欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解es6塊級作用域的使用

 更新時間:2019年03月28日 11:48:35   作者:夕水  
這篇文章主要介紹了深入理解es6塊級作用域的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一.var 聲明與變量提升機(jī)制

在JavaScript中使用var定義一個變量,無論是定義在全局作用域函數(shù)函數(shù)的局部作用域中,都會被提升到其作用域的頂部,這也是JavaScript定義變量的一個令人困惑的地方。由于es5沒有像其它類C語言一樣的塊級作用域,因此es6增加了let定義變量,用來創(chuàng)建塊級作用域。

我們來看一個var定義變量的示例:

function  setName(){
  if(condition){
    var name = 'loho';
    console.log(name);
  }else{
    console.log(name);
  }
}

var student = 'eveningwater';
setName();

以上代碼可以理解成如下:

var student;
function setName(){
  var name;
  if(condition){
    name = 'loho';
    console.log(name);//loho
  }else{
   console.log(name);//undefined
  }
}
student = 'eveningwater';
setName();

二.塊級聲明

塊級聲明意在指定一個塊級作用域,使得塊級作用域中所定義的變量無法再全局被訪問到,塊級作用域也被稱為詞法作用域。

塊級作用域存在于兩個地方:

  1. 函數(shù)內(nèi)部。
  2. 指定代碼塊中。(即"{"和"}"之間的區(qū)域)

1.let 聲明

let聲明同var聲明用法一致,唯一的區(qū)別在于,let聲明將變量限制在一個塊內(nèi),這樣就形成了一個塊級作用域,因此也就不會存在變量的提升了。

例如前面的示例,我們可以寫成如下:

let stundent = 'eveningwater';
function setName(){
  if(condition){
    let name = 'loho';
    console.log(name);//loho
  }else{
    //如果條件為false執(zhí)行到這里
    console.log(name);//不返回值
  }
}
setName();

2.禁止重聲明

在使用let定義變量之前如果已經(jīng)聲明了相同的變量,就會報錯。因此不能重復(fù)聲明變量。如以下示例:

var name = 'eveningwater';
//報錯,重復(fù)聲明
let name = 'loho';

當(dāng)然這兩個變量必須是在同一個作用域中,如果是不同作用域中,則不會報錯。但有可能會遮蔽第一次聲明的變量。如以下示例:

var name = 'eveningwater';
if(condition){
  //不會報錯
  let name = 'loho';
}

3.const聲明

使用const標(biāo)識符所聲明的變量必須要初始化,因此這個聲明的就是一個常量。如下例:

const name='eveningwater';//正確
const name;//錯誤,未初始化

const聲明同let聲明一樣,也是創(chuàng)建了一個塊級作用域,在這個塊級作用域之外是無法訪問到所聲明的變量的。換句話說,就是const所聲明的變量不會有變量提升機(jī)制。如下例:

if(condition){
    const name = 'eveningwater';
    console.log(name);//'eveningwater'
}
//錯誤
console.log(name);

同樣的const也不能重復(fù)聲明,如下例:

var name = 'eveningwater';
//錯誤,不能重復(fù)聲明
const name = 'loho';

但也可以在不同作用域中重復(fù)聲明,如下例:

var name = 'eveningwater';
if(condition){
  const name = 'loho';
  console.log(name);//loho,屏蔽全局定義的變量
}

盡管const聲明與let聲明有太多相似的地方,但const聲明也有一處與let聲明不同,那就是const聲明的變量不能被賦值,無論是在非嚴(yán)格模式下還是在嚴(yán)格模式下,都不能對const聲明的變量進(jìn)行賦值。如下例:

const name = 'eveningwater';
//錯誤
name = 'loho';

不過,如果定義的是一個對象,可以對對象的值進(jìn)行修改,如下例:

const student = {
  name:'eveningwater'
}
student.name = 'loho';//沒問題
//錯誤,相當(dāng)于賦值修改對象
student = {
  name:'loho'
}

4.臨時死區(qū)

前面提到let和const聲明的變量都不會提升到作用域的頂部,因此在使用這兩個標(biāo)識符聲明之前訪問會報錯,即使是typeof操作符也會觸發(fā)引用錯誤。如下例:

console.log(typeof name);//報錯
const name = 'eveningwater';

由于第一行代碼就報錯了,因此后續(xù)的聲明變量語句不會執(zhí)行,此時就出現(xiàn)了JavaScript社區(qū)所謂的"臨時死區(qū)"(temporal dead zone).雖然這里示例是const聲明,但let聲明也是一樣的。

但如果在const或let聲明的變量的作用域之外使用typeof操作符監(jiān)測卻不會報錯,只不過會返回undefined。如下例:

console.log(typeof name);//undefined
if(condition){
  let name = 'eveningwater';
}

5.循環(huán)中的塊級作用域綁定

我們在使用var聲明變量的時候,總會遇到這樣的情況,如下:

for(var i = 0;i < 100;i++){
  //執(zhí)行某些操作
}
//這里也能訪問到變量i
console.log(i);//100

我們可以使用let聲明將變量i限制在循環(huán)中,此時再在循環(huán)作用域之外訪問變量i就會報錯了,因為let聲明已經(jīng)為循環(huán)創(chuàng)建了一個塊級作用域。如下:

for(let i = 0;i < 100;i++){
  //執(zhí)行某些操作
}
//報錯
console.log(i);

6.循環(huán)中的創(chuàng)建函數(shù)

在使用var聲明變量的循環(huán)中,創(chuàng)建一個函數(shù)非常的困難,如下例:

var func = [];
for(var i = 0;i < 5;i++){
  func.push(function(){
    console.log(i);
  })
}
func.forEach(function(func){
  func();
});

你可能預(yù)期想的是打印從0到5之間,即0,1,2,3,4的數(shù)字,但實際上答案并不是如此。由于函數(shù)有自己的作用域,因此在向數(shù)組中添加函數(shù)的時候,實際上循環(huán)已經(jīng)運行完成,因此每次打印變量i的值都相當(dāng)于是在全局中訪問變量i的值,即i = 5這個值,因此實際上答案最終會返回5次5.

在es5中,我們可以使用函數(shù)表達(dá)式(IIFE)來解決這個問題,因為函數(shù)表達(dá)式會創(chuàng)建一個自己的塊級作用域。如下:

var func = [];
for(var i = 0;i < 5;i++){
  (function(i){
    func.push(function(){
      console.log(i);
    })
  })(i)
}
func.forEach(function(func){
  func();//這就是你想要的答案,輸出0,1,2,3,4
});

但事實上有了es6的let聲明,我們不必如此麻煩,只需要將var變成let聲明就可以了,如下:

var func = [];
for(let i = 0;i < 5;i++){
  func.push(function(){
    console.log(i);
  })
}
func.forEach(function(func){
  func();//輸出0,1,2,3,4
})

但是這里不能使用const聲明,因為前面提到過,const聲明并初始化了一個常量之后是不能被修改的,只能在對象中被修改值。如以下示例就會報錯:

//在執(zhí)行循環(huán)i++條件的時候就會報錯
for(const i = 0;i < len;i++){
  console.log(i);
}

因為i++這個語句就是在嘗試修改常量i的值,因此不能將const聲明用在for循環(huán)中,但可以將const聲明用在for-in或者for-of循環(huán)中。如下:

var func = [];
var obj = {
  name:'eveningwater',
  age:22
}
for(let key in obj){
 func.push(function(){
   console.log(key)
 })
}
func.forEach(function(func){
  func();//name,age
});
//以下也沒問題
var func = [];
var obj = {
  name:'eveningwater',
  age:22
}
for(const key in obj){
  func.push(function(){
    console.log(key)
  })
}
func.forEach(function(func){
 func();//name,age
});

這里并沒有修改key的值,因此使用const和let聲明都可以,同理for-of循環(huán)也是一樣的道理。for-of循環(huán)是es6的新增的循壞。。

7.全局作用域綁定

let,const聲明與var聲明還有一個區(qū)別就是三者在全局作用域中的行為。當(dāng)使用var聲明一個變量時,會在全局作用域(通常情況下是瀏覽器window對象)中創(chuàng)建一個全局屬性,這也就意味著可能會覆蓋window對象中已經(jīng)存在的一個全局變量。如下例:

console.log(window.Array);//應(yīng)該返回創(chuàng)建數(shù)組的構(gòu)造函數(shù),即f Array(){}
var Array = '這是數(shù)組';
console.log(window.Array);//返回'這是數(shù)組';

從上例,我們可以知道即使全局作用域中已經(jīng)定義了Array變量或者已經(jīng)存在了Array屬性,但我們之后定義的Array變量則會覆蓋之前已經(jīng)定義好的或者已經(jīng)存在的Array變量(屬性)。

但是es6的let和const聲明則不會出現(xiàn)這種情況,let和const聲明會創(chuàng)建一個新的綁定,也就是說不會成為window對象的屬性。換句話說,就是所聲明的變量不會覆蓋全局變量,而只會遮蔽它。如下例:

let Array = '這是數(shù)組';
console.log(Array);//'這是數(shù)組‘;
console.log(window.Array);//應(yīng)該返回創(chuàng)建數(shù)組的構(gòu)造函數(shù),即f Array(){}

這也就是說window.Array !== Array這個等式返回布爾值true。

8.塊級綁定的最佳實踐

在使用es6塊級聲明變量中,最佳實踐是如果確定后續(xù)不會改變這個變量的值,用const聲明,如果確定要改變這個變量的值,則用let聲明。因為預(yù)料外的變量值的改變時很多bug出現(xiàn)的源頭。如下示例:

function eveningWater(){};
eveningWater.prototype.name = 'eveningwater';
let ew = new eveningWater();
//定義不能被修改的變量,也就是用于判斷實例類型的屬性
const _constructor = ew.constructor;
//可以改變自定義的名字屬性
let name = ew.name;
if(_constructor === eveningWater || _constuctor === Object){
 console.log(_constructor);
}else{
  name = 'loho';
  console.log(name)
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 彈出窗口并且此窗口帶有半透明的遮罩層效果

    彈出窗口并且此窗口帶有半透明的遮罩層效果

    這篇文章主要介紹了如何點擊一個按鈕實現(xiàn)彈出一個居中窗口,并且此窗口帶有半透明的遮罩層效果,需要的朋友可以參考下
    2014-03-03
  • 一文搞懂JavaScript中的內(nèi)存泄露

    一文搞懂JavaScript中的內(nèi)存泄露

    以前我們說的內(nèi)存泄漏,通常發(fā)生在后端,但是不代表前端就不會有內(nèi)存泄漏。特別是當(dāng)前端項目變得越來越復(fù)雜后,前端也逐漸稱為內(nèi)存泄漏的高發(fā)區(qū)。本文就帶大家了解一下Javascript的內(nèi)存泄漏
    2022-06-06
  • 深入理解JavaScript系列(13) This? Yes,this!

    深入理解JavaScript系列(13) This? Yes,this!

    在這篇文章里,我們將討論跟執(zhí)行上下文直接相關(guān)的更多細(xì)節(jié)。討論的主題就是this關(guān)鍵字。實踐證明,這個主題很難,在不同執(zhí)行上下文中this的確定經(jīng)常會發(fā)生問題
    2012-01-01
  • JavaScript針對SPA應(yīng)用的前端優(yōu)化策略概述

    JavaScript針對SPA應(yīng)用的前端優(yōu)化策略概述

    前端性能優(yōu)化是Web開發(fā)中非常重要的一環(huán),優(yōu)化能夠有效地提高網(wǎng)站的加載速度和用戶體驗,而對于SPA來說,由于其特殊的加載方式和數(shù)據(jù)交互方式,其優(yōu)化策略也具有一定的特殊性,需要詳細(xì)了解可以參考下文
    2023-05-05
  • js函數(shù)名與form表單元素同名沖突的問題

    js函數(shù)名與form表單元素同名沖突的問題

    本篇文章主要是對js函數(shù)名與form表單元素同名沖突的問題進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-03-03
  • 深入淺出JS的Object.defineProperty()

    深入淺出JS的Object.defineProperty()

    這篇文章主要介紹了深入淺出JS的Object.defineProperty(),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-06-06
  • 實用的JS正則表達(dá)式(手機(jī)號碼/IP正則/郵編正則/電話等)

    實用的JS正則表達(dá)式(手機(jī)號碼/IP正則/郵編正則/電話等)

    實用的JS正則表達(dá)式(手機(jī)號碼/IP正則/郵編正則/電話等),經(jīng)驗積累,感興趣的朋友可以了解下,一定會對你有幫助的
    2013-01-01
  • IE下JS讀取xml文件示例代碼

    IE下JS讀取xml文件示例代碼

    JS讀取xml文件具體步驟為:創(chuàng)建DOM對象、加載xml文件(僅適用于IE)附示例代碼,感興趣的朋友可以參考下,希望對大家有所幫助
    2013-08-08
  • JS獲取當(dāng)前網(wǎng)頁大小以及屏幕分辨率等

    JS獲取當(dāng)前網(wǎng)頁大小以及屏幕分辨率等

    這篇文章主要介紹了JS獲取當(dāng)前網(wǎng)頁大小以及屏幕分辨率等,方法雖簡單,但比較實用,需要的朋友可以參考下
    2014-09-09
  • JavaScript學(xué)習(xí)筆記之DOM操作實例分析

    JavaScript學(xué)習(xí)筆記之DOM操作實例分析

    這篇文章主要介紹了JavaScript學(xué)習(xí)筆記之DOM操作,結(jié)合實例形式分析了javascript針對dom元素的獲取、設(shè)置相關(guān)操作常用函數(shù)使用技巧,需要的朋友可以參考下
    2019-01-01

最新評論