ES6--JavaScript的第六個版本

来源:https://www.cnblogs.com/xuxiaoyu/archive/2019/03/06/10471554.html
-Advertisement-
Play Games

一、新的變數聲明方式 let/cons 與var不同,新的變數聲明方式帶來了一些不一樣的特性,其中最重要的兩個特性就是提供了塊級作用域與不再具備變數提升。 若是對變數提升不怎麼瞭解的話可以去參考我的其他文章 javascript預編譯的過程 。 什麼是塊級作用域膩? 寫在 “{}” 內的內容 都是塊 ...


 一、新的變數聲明方式 let/cons

與var不同,新的變數聲明方式帶來了一些不一樣的特性,其中最重要的兩個特性就是提供了塊級作用域與不再具備變數提升。

若是對變數提升不怎麼瞭解的話可以去參考我的其他文章   javascript預編譯的過程 。

什麼是塊級作用域膩?

寫在 “{}” 內的內容   都是塊級作用域。

在es6之前,我們想保護一個變數怎麼辦,將其放在一個立即執行函數裡面,寫在局部作用域中。

這樣寫是不是挺麻煩的捏,多謝幾個單詞不花時間麽?!

在ES6中,我們想保護一個變數 只要 寫在花括弧中就好了。

{

  let   a=10;

}

下麵有兩個例子:

{
    let a = 20;
}

console.log(a);  // a is not defined
//寫在塊級作用域中的內容會被保護起來,所以會列印  a is not defined

而這個簡單的例子,會被編譯為:

{
let _a = 20;
}
console.log(a); // a is not defined


// ES5
console.log(a); // undefined
var a = 20;
//  在es5中var一個變數 會變數提升
//  如同
//  var a;
//  console.log(a); //從上向下順序執行 當然會列印 undefined 的捏。
//  a=20


// ES6 
console.log(a); // a is not defined 
let a = 20;
//變數不會提升 列印時當然是 a is not defined

當然,你的代碼編譯成為了ES5之後,仍然會存在變數提升,因此這一點只需要我們記住即可。

在實際使用中,也需要儘量避免使用變數提升的特性帶來的負面影響。只有在面試題中,才會對變數提升不停的濫用。使用ES6,我們需要全面使用let/const替換var,那麼什麼時候用let,什麼時候用const就成為了一個大家要熟練區分的一個知識點。

我們常常使用let來聲明一個值會被改變的變數,而使用const來聲明一個值不會被改變的變數,也可以稱之為常量。當值為基礎數據類型時,那麼這裡的值,就是指值本身。而當值對應的為引用數據類型時,那麼我這裡說的值,則表示指向該對象的引用。

這裡需要註意,正因為該值為一個引用,只需要保證引用不變就可以,我們仍然可以改變該引用所指向的對象。當我們試圖改變const聲明的變數時,則會報錯。

寫幾個例子,大家可以仔細揣摩一下:

let a = null;
a = 20;
const obDev = {
    a: 20,
    b: 30
}

obDev.a = 30;

console.log(obDev); // Object {a: 30, b: 30}
const fn = function() {}
const a = obDev.a;
... ...

只要抓住上面我說的特性,那麼在使用let/const時就會顯得游刃有餘。根據我自己的經驗,使用const的場景要比使用let的場景多很多。

 

二,解構賦值

我們經常定義許多對象和數組,然後有組織地從中提取相關的信息片段。在ES6中添加了可以簡化這種任務的新特性:解構。解構是一種打破數據結構,將其拆分為更小部分的過程。

在ES5中,開發者們為了從對象和數組中獲取特定數據並賦值給變數,編寫了許多看起來同質化的代碼

let options = {
    repeat: true,
    save: false
};
// 從對象中提取數據
let repeat = options.repeat,
save = options.save;

  這段代碼從options對象中提取repeat和save的值,並將其存儲為同名局部變數,提取的過程極為相似

  如果要提取更多變數,則必須依次編寫類似的代碼來為變數賦值,如果其中還包含嵌套結構,只靠遍歷是找不到真實信息的,必須要深入挖掘整個數據結構才能找到所需數據

  所以ES6添加瞭解構功能,將數據結構打散的過程變得更加簡單,可以從打散後更小的部分中獲取所需信息

 對象解構:

對象字面量的語法形式是在一個賦值操作符左邊放置一個對象字面量。

let node = {
    type: "Identifier",
    name: "foo"
};
let { type, name } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
let node = {
    type: "Identifier",
    name: "foo"
},
type = "Literal",
name = 5;
// 使用解構來分配不同的值
({ type, name } = node);
console.log(type); // "Identifier"
console.log(name); // "foo"

 

在這個示例中,聲明變數type和name時初始化了一個值,在後面幾行中,通過解構賦值的方法,從node對象讀取相應的值重新為這兩個變數賦值

  [註意]一定要用一對小括弧包裹解構賦值語句,JS引擎將一對開放的花括弧視為一個代碼塊。語法規定,代碼塊語句不允許出現在賦值語句左側,添加小括弧後可以將塊語句轉化為一個表達式,從而實現整個解構賦值過程。

數組解構:

與對象解構的語法相比,數組解構就簡單多了,它使用的是數組字面量,且解構操作全部在數組內完成,而不是像對象字面量語法一樣使用對象的命名屬性

let colors = [ "red", "green", "blue" ];
let [ firstColor, secondColor ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"

  在這段代碼中,我們從colors數組中解構出了"red"和"green"這兩個值,並分別存儲在變數firstColor和變數secondColor中。在數組解構語法中,我們通過值在數組中的位置進行選取,且可以將其存儲在任意變數中,未顯式聲明的元素都會直接被忽略

  在解構模式中,也可以直接省略元素,只為感興趣的元素提供變數名

let colors = [ "red", "green", "blue" ];
let [ , , thirdColor ] = colors;
console.log(thirdColor); // "blue"

  這段代碼使用解構賦值語法從colors中獲取第3個元素,thirdColor前的逗號是前方元素的占位符,無論數組中的元素有多少個,都可以通過這種方法提取想要的元素,不需要為每一個元素都指定變數名

混合解構:

  可以混合使用對象解構和數組解構來創建更多複雜的表達式,如此一來,可以從任何混雜著對象和數組的數據解構中提取想要的信息

let node = {
    type: "Identifier",
    name: "foo",
    loc: {
        start: {
            line: 1,
            column: 1
        },
        end: {
            line: 1,
            column: 4
        }
    },
    range: [0, 3]
};
let {
    loc: { start },
    range: [ startIndex ]
} = node;
console.log(start.line); // 1
console.log(start.column); // 1
console.log(startIndex); // 0

  這段代碼分別將node.loc.start和node.range[0]提取到變數start和startlndex中

  解構模式中的loc和range僅代表它們在node對象中所處的位置(也就是該對象的屬性)。當使用混合解構的語法時,則可以從node提取任意想要的信息。這種方法極為有效,尤其是從JSON配置中提取信息時,不再需要遍歷整個結構了

 

三、 箭頭函數的使用

之前我說ES6顛覆了js的編碼習慣,箭頭函數的使用占了很大一部分。

首先是寫法上的不同:

// es5
var fn = function(a, b) {
    return a + b;
}

// es6 箭頭函數寫法,當函數直接被return時,可以省略函數體的括弧
const fn = (a, b) => a + b;

// es5
var foo = function() {
    var a = 20var b = 30;
    return a + b;
}

// es6
const foo = () => {
   const a = 20;
   const b = 30;
   return a + b;
}

箭頭函數可以替換函數表達式,但是不能替換函數聲明

其次還有一個至關重要的一點,那就是箭頭函數中,沒有this。如果你在箭頭函數中使用了this,那麼該this一定就是外層的this。

也正是因為箭頭函數中沒有this,因此我們也就無從談起用call/apply/bind來改變this指向。記住這個特性,能讓你在react組件之間傳值時少走無數彎路。

var person = {
    name: 'tom',
    getName: function() {
        return this.name;
    }
}

// 我們試圖用ES6的寫法來重構上面的對象
const person = {
    name: 'tom',
    getName: () => this.name
}

// 但是編譯結果卻是
var person = {
    name: 'tom',
    getName: function getName() {
        return undefined.name;
    }
};

在ES6中,會預設採用嚴格模式,因此this也不會自動指向window對象了,而箭頭函數本身並沒有this,因此this就只能是undefined,這一點,在使用的時候,一定要慎重慎重再慎重,不然踩了坑你都不知道自己錯在哪!這種情況,如果你還想用this,就不要用使用箭頭函數的寫法。

// 可以稍做改動
const person = {
    name: 'tom',
    getName: function() {
        return setTimeout(() => this.name, 1000);
    }
}

// 編譯之後變成
var person = {
    name: 'tom',
    getName: function getName() {
        var _this = this;  // 使用了我們在es5時常用的方式保存this引用

        return setTimeout(function () {
            return _this.name;
        }, 1000);
    }
};

先記住箭頭函數的寫法,並留意箭頭函數中關於this的特殊性,更過實踐與註意事項我們在封裝react組件時再慢慢來感受。

還有就是  原函數中  arguments (實參) 在箭頭函數中是是用不了的。

 

四,promise  (承諾)

 他就是一個對象,主要是用來處理非同步數據的。

在promise中,有三種狀態:

pending(等待,處理中)   -->  1.resolve(完成)   2.rejected(失敗,拒絕)。

又,這三種狀態的變化只有兩種模式,並且一旦狀態改變,就不會再變:

  1、非同步操作從pending到resolved;

  2、非同步操作從pending到rejected;

好了,既然它是屬於ES6規範,我們再通過chrome,直接列印出Promise,看看這玩意:

 

恩,一目瞭然,Promise為構造函數,歐克,這樣通過它,我們就可以實例化自己的Promise對象了,並加以利用。 

Promise對象中的then方法

可以接收構造函數中處理的狀態變化,並分別對應執行。then方法有2個參數,第一個函數接收resolved狀態的執行,第二個參數接收reject狀態的執行。

function fn(num) {
    return new Promise(function(resolve, reject) {
        if (typeof num == 'number') {
            resolve();
        } else {
            reject();
        }
    }).then(function() {
        console.log('參數是一個number值');
    }, function() {
        console.log('參數不是一個number值');
    })
}

fn('hahha');
fn(1234);

 

then方法的執行結果也會返回一個Promise對象。因此我們可以進行then的鏈式執行,這也是解決回調地獄的主要方式。

function fn(num) {
    return new Promise(function(resolve, reject) {
        if (typeof num == 'number') {
            resolve();
        } else {
            reject();
        }
    })
    .then(function() {
        console.log('參數是一個number值');
    })
    .then(null, function() {
        console.log('參數不是一個number值');
    })
}

fn('hahha');
fn(1234);

 

then(null, function() {}) 就等同於catch(function() {})

catch的用法

我們知道Promise對象除了then方法,還有一個catch方法,它是做什麼用的呢?其實它和then的第二個參數一樣,用來指定reject的回調,用法是這樣:
getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

效果和寫在then的第二個參數裡面一樣。不過它還有另外一個作用:在執行resolve的回調(也就是上面then中的第一個參數)時,如果拋出異常了(代碼出錯了),那麼並不會報錯卡死js,而是會進到這個catch方法中。請看下麵的代碼:

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
    console.log(somedata); //此處的somedata未定義
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});
  在resolve的回調中,我們console.log(somedata);而somedata這個變數是沒有被定義的。如果我們不用Promise,代碼運行到這裡就直接在控制台報錯了,不往下運行了。但是在這裡,會得到這樣的結果:     也就是說進到catch方法裡面去了,而且把錯誤原因傳到了reason參數中。即便是有錯誤的代碼也不會報錯了,這與我們的try/catch語句有相同的功能。

all的用法

Promise的all方法提供了並行執行非同步操作的能力,並且在所有非同步操作執行完後才執行回調。我們仍舊使用上面定義好的runAsync1、runAsync2、runAsync3這三個函數,看下麵的例子:  
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});
用Promise.all來執行,all接收一個數組參數,裡面的值最終都算返回Promise對象。這樣,三個非同步操作的並行執行的,等到它們都執行完後才會進到then裡面。那麼,三個非同步操作返回的數據哪裡去了呢?都在then裡面呢,all會把所有非同步操作的結果放進一個數組中傳給then,就是上面的results。所以上面代碼的輸出結果就是:   有了all,你就可以並行執行多個非同步操作,並且在一個回調中處理所有的返回數據,是不是很酷?有一個場景是很適合用這個的,一些游戲類的素材比較多的應用,打開網頁時,預先載入需要用到的各種資源如圖片、flash以及各種靜態文件。所有的都載入完後,我們再進行頁面的初始化。

race的用法

all方法的效果實際上是「誰跑的慢,以誰為準執行回調」,那麼相對的就有另一個方法「誰跑的快,以誰為準執行回調」,這就是race方法,這個詞本來就是賽跑的意思。race的用法與all一樣,我們把上面runAsync1的延時改為1秒來看一下:
Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});
這三個非同步操作同樣是並行執行的。結果你應該可以猜到,1秒後runAsync1已經執行完了,此時then裡面的就執行了。結果是這樣的:

 

 



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 此篇博客整理了常用的輪播效果,適用於所有開發人員 swipe是當下相對而言較好用的輪播插件,下麵是博主整理的demo源代碼,可直接上手(備註:需自己手動swipe所需的j和css) 此段代碼總共是有三個詳細效果,並且備註了初始化js對應的html,和使用swipe當中所需要用到的一些小的屬性控制方法 ...
  • 一、1、color: 文本顏色 預定義文本顏色值,如red,blue等 十六進位的顏色值 #fff白色 建議常用的表示方法 RGB代碼,如紅色可以表示為rgb(255,0,0)或rgb(100%,%0,%0) 2、行間距: line-height line-height: 10px; 3、text- ...
  • element的table中使用 <template slot-scope="scope"> </template> 包裹想要插入的input,或者select等HTML元素,<el-table>綁定一個的數組對象,在input或者select等HTML元素使用 v-model="scope.row ...
  • 隨著科技的進步,及人們日常生活節奏的加快,我們通常花費在手機等移動設備上的時間比使用電腦的時間越來越多,為了適應市場及用戶的轉變,越來越多的服務從PC端轉向移動端,就導致移動端有著強大的發展前景和巨大的市場,作為一個Web高級前端開發工程師,移動端頁面佈局也成了我們必須掌握的技能之一。 ...
  • 在做網頁時前端時,使用IE打開時會出現標題欄DIV被遮擋PDF遮擋, 後在stackoverflow中查到是IE瀏覽器的問題:鏈接https://stackoverflow.com/questions/12911428/z-index-does-not-work-in-internet-explor ...
  • 3D建築,bim技術,3d庫房,3d檔案室,3d密集架,webGL,threejs,3d機房 ...
  • 直接進入正題,滑鼠跟隨,顧名思義,就是元素會跟隨著滑鼠的移動而作出相應的運動。大概類似於這樣: 通常而言,CSS 負責表現,JavaScript 負責行為。而滑鼠跟隨這種效果屬於行為,要實現通常都需要藉助 JS。 當然,本文的重點,就是介紹如何在不藉助 JS 的情況下使用 CSS 來模擬實現一些滑鼠 ...
  • Web前端工程師是當前各大企業都比較稀缺的人才,薪資待遇和就業前景都很不錯。不論是專業還是非專業,有基礎亦或是無基礎,都想通過學習Web前端實現高薪就業。 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...