主頁 > 企業開發 > ES6核心特性

ES6核心特性

2021-04-01 20:26:33 企業開發

目錄
  • 前言
  • 一、開發環境配置
    • 1.babel
    • 為啥需要babel?
    • 如何配置babel?
    • 驗證配置是否成功
    • 2.webpack
    • 為啥要使用WebPack?
    • 如何配置webpack?
  • 二、塊級作用域
  • 三、陣列的擴展
    • 1. Array.from() : 將偽陣列物件或可遍歷物件轉換為真陣列
    • 2.Array.of(v1, v2, v3) : 將一系列值轉換成陣列
    • 3.陣列實體的 find() 和 findIndex()
    • 4.陣列實體的includes()
    • 5.陣列實體的 entries(),keys() 和 values()
  • 四、箭頭函式
    • 1. 縮減代碼
    • 2. 改變this指向
    • 3.使用注意點
  • 五、rest 引數
  • 六、展開運算子
  • 七、解構賦值----更方便的資料訪問
    • 1.解構為何有用?
    • 2.物件
    • 3.陣列
    • 4.注意點
  • 八、模板字串(template string)
  • 九、Class 和傳統建構式有何區別
    • 對比在傳統建構式和 ES6 中分別如何實作類:
    • 對比在傳統建構式和 ES6 中分別如何實作繼承:
    • Class 和傳統建構式有何區別
  • 十、Promise的基本使用和原理
    • Promise原理
    • Promise的使用流程
  • 十一、Iterator 和 for...of 回圈
    • 1.Iterator的作用:
    • 2.原生具備iterator介面的資料(可用for of遍歷)
    • 3.幾種遍歷方式比較
  • 十二、ES6模塊化
  • 后記

前言

ES6 雖提供了許多新特性,但我們實際作業中用到頻率較高并不多,根據二八法則,我們應該用百分之八十的精力和時間,好好專研這百分之二十核心特性,將會收到事半功倍的奇效!寫文章不容易,請大家多多支持與關注!

一、開發環境配置

這部分著重介紹:babel 編譯ES6語法,如何用webpack實作模塊化,

1.babel

為啥需要babel?

ES6 提供了許多新特性,但并不是所有的瀏覽器都能夠完美支持,下圖是各個瀏覽器對ES6兼容性一覽表(以export為例)

export各個瀏覽器兼容性一覽表

由上圖可知,有些瀏覽器對于ES6并不是很友好,針對 ES6 的兼容性問題,很多團隊為此開發出了多種語法決議轉換工具(比如babel,jsx,traceur 等),可以把我們寫的 ES6 語法轉換成 ES5,相當于在 ES6 和瀏覽器之間做了一個翻譯官,其中Babel是一個廣泛使用的轉碼器,可以將ES6代碼轉為ES5代碼,從而在現有環境執行,

如何配置babel?

·首先要先安裝node.js,運行npm init,然后會生成package.json檔案
·npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest
·創建并配置.babelrc檔案//存放在專案的根目錄下,與node_modules同級
·npm install -g babel-cli
·babel-version 

Babel的組態檔是.babelrc,存放在專案的根目錄下,該檔案用來設定轉碼規則和插件,具體內容如下:

//.babelrc檔案
{
    "presets": ["es2015", "latest"],
    "plugins": []
} 

驗證配置是否成功

·創建./src/index.js
·內容:[1,2,3].map(item=>item+1);
·運行babel./src/index.js 

運行后得到以下部分,說明已經成功配置了babel

"use strict";
[1, 2, 3].map(function (item) {
  return item + 1;
}); 

2.webpack

為啥要使用WebPack?

現今的很多網頁其實可以看做是功能豐富的應用,它們擁有著復雜的JavaScript代碼和一大堆依賴包,模快化工具就應運而生了,其中webpack 功能強大深受人們喜愛,
Webpack的作業方式是:把你的專案當做一個整體,通過一個給定的主檔案(如:index.js),Webpack將從這個檔案開始找到你的專案的所有依賴檔案,使用loaders處理它們,最后打包為一個(或多個)瀏覽器可識別的JavaScript檔案,

如何配置webpack?

·npm install webpack babel-loader --save-dev
·創建并配置 webpack.config.js//webpack.config.js檔案與package.json同級
·配置 package.json中的scripts
·運行 npm start 
//配置 webpack.config.js  針對.js結尾的檔案除了node_modules都用babel決議
module.exports = {
    entry: './src/index.js',
    output: {
        path: __dirname,
        filename: './build/bundle.js'
    },
    module: {
        rules: [{
            test: /.js?$/,
            exclude: /(node_modules)/,
            loader: 'babel-loader'
        }]
    }
} 
//配置 package.json中的scripts
"scripts": {
    "start": "webpack",
    "test": "echo "Error: no test specified" && exit 1"
  } 

二、塊級作用域

ES5 只有全域作用域和函式作用域(例如,我們必須將代碼包在函式內來限制作用域),這導致很多問題:

情況1:內層變數覆寫外層變數

var tmp = new Date();
function f() {
  console.log(tmp); //undefined
  if (false) {   
    var tmp = "hello world";
  }
} 

情況2:變數泄露,成為全域變數

var s = 'hello';
for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}
console.log(i); // 5 

ES6 提供 let 和 const 來代替 var 宣告變數,新的宣告方式支持用大括號表示的塊級作用域,這會帶來一些好處:

1.不再需要立即執行的函式運算式(IIFE)
在 ES5 中,我們需要構造一個立即執行的函式運算式去保證我們不污染全域作用域,在 ES6中, 我們可以使用更簡單的大括號({}),然后使用 const 或者 let 代替 var 來達到同樣的效果,

2.回圈體中的閉包不再有問題
在 ES5 中,如果回圈體內有產生一個閉包,訪問閉包外的變數,會產生問題,在 ES6,你可以使用 “let” 來避免問題,

3.防止重復宣告變數
ES6 不允許在同一個作用域內用 let 或 const 重復宣告同名變數,這對于防止在不同的 js 庫中存在重復宣告的函式運算式十分有幫助,

三、陣列的擴展

1. Array.from() : 將偽陣列物件或可遍歷物件轉換為真陣列

如果一個物件的所有鍵名都是正整數或零,并且有length屬性,那么這個物件就很像陣列,稱為偽陣列,典型的偽陣列有函式的arguments物件,以及大多數 DOM 元素集,還有字串,

...
<button>測驗1</button>
<br>
<button>測驗2</button>
<br>
<button>測驗3</button>
<br>
<script type="text/javascript">
let btns = document.getElementsByTagName("button")
console.log("btns",btns);//得到一個偽陣列
btns.forEach(item=>console.log(item)) Uncaught TypeError: btns.forEach is not a function
</script> 

針對偽陣列,沒有陣列一般方法,直接遍歷便會出錯,ES6新增Array.from()方法來提供一種明確清晰的方式以解決這方面的需求,

Array.from(btns).forEach(item=>console.log(item))將偽陣列轉換為陣列 

2.Array.of(v1, v2, v3) : 將一系列值轉換成陣列

當呼叫 new Array( )構造器時,根據傳入引數的型別與數量的不同,實際上會導致一些不同的結果, 例如:

let items = new Array(2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // undefined
console.log(items[1]) ; 
let items = new Array(1, 2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // 1
console.log(items[1]) ; // 2 

當使用單個數值引數來呼叫 Array 構造器時,陣列的長度屬性會被設定為該引數, 如果使用多個引數(無論是否為數值型別)來呼叫,這些引數也會成為目標陣列的項,陣列的這種行為既混亂又有風險,因為有時可能不會留意所傳引數的型別,

ES6 引入了Array.of( )方法來解決這個問題,該方法的作用非常類似Array構造器,但在使用單個數值引數的時候并不會導致特殊結果,Array.of( )方法總會創建一個包含所有傳入引數的陣列,而不管引數的數量與型別

let items = Array.of(1, 2);
console.log(items.length); // 2
console.log(items[0]); // 1
console.log(items[1]); // 2
items = Array.of(2);
console.log(items.length); // 1
console.log(items[0]); // 2 

Array.of基本上可以用來替代Array()或newArray(),并且不存在由于引數不同而導致的多載,而且他們的行為非常統一,

3.陣列實體的 find() 和 findIndex()

陣列實體的find方法,用于找出第一個符合條件的陣列成員,它的引數是一個回呼函式,所有陣列成員依次執行該回呼函式,直到找出第一個回傳值為true的成員,然后回傳該成員,如果沒有符合條件的成員,則回傳undefined,

[1, 4, -5, 10].find((n) => n < 0) // -5 

陣列實體的findIndex方法的用法與find方法非常類似,回傳第一個符合條件的陣列成員的位置,如果所有成員都不符合條件,則回傳-1,

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2 

4.陣列實體的includes()

Array.prototype.includes方法回傳一個布林值,表示某個陣列是否包含給定的值,該方法的第二個引數表示搜索的起始位置,默認為0,如果第二個引數為負數,則表示倒數的位置,如果這時它大于陣列長度(比如第二個引數為-4,但陣列長度為3),則會重置為從0開始,

[1, 2, 3].includes(2)   // true
[1, 2, 3].includes(3, -1); // true
[1, 2, 3, 5, 1].includes(1, 2); // true 

沒有該方法之前,我們通常使用陣列的indexOf方法,檢查是否包含某個值,indexOf方法有兩個缺點,一是不夠語意化,它的含義是找到引數值的第一個出現位置,所以要去比較是否不等于-1,表達起來不夠直觀,二是,它內部使用嚴格相等運算子(===)進行判斷,這會導致對NaN的誤判

[NaN].indexOf(NaN) // -1
[NaN].includes(NaN) // true 

5.陣列實體的 entries(),keys() 和 values()

ES6 提供entries(),keys()和values(),用于遍歷陣列,它們都回傳一個遍歷器物件,可以用for...of回圈進行遍歷,唯一的區別是keys()是對鍵名的遍歷、values()是對鍵值的遍歷,entries()是對鍵值對的遍歷,

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b" 

四、箭頭函式

ES6 允許使用“箭頭”(=>)定義函式,它主要有兩個作用:縮減代碼和改變this指向,接下來我們詳細介紹:

1. 縮減代碼

const double1 = function(number){
   return number * 2;   //ES5寫法
}
const double2 = (number) => {
 return number * 2;    //ES6寫法
}
const double4 = number => number * 2; //可以進一步簡化 

多個引數記得加括號

 const double6 = (number,number2) => number + number2; 

如果箭頭函式的代碼塊部分多于一條陳述句,就要使用大括號將它們括起來,并且使用return陳述句回傳

 const double = (number,number2) => {
   sum = number + number2 
   return sum;
 } 

由于大括號被解釋為代碼塊,所以如果箭頭函式直接回傳一個物件,必須在物件外面加上括號,否則會報錯

// 報錯
let getTempItem = id => { id: id, name: "Temp" };
// 不報
let getTempItem = id => ({ id: id, name: "Temp" }); 

此外還有個好處就是簡化回呼函式

// 正常函式寫法
[1,2,3].map(function (x) {
  return x * x;
});
// 箭頭函式寫法
[1,2,3].map(x => x * x);//[1, 4, 9] 

2. 改變this指向

長期以來,JavaScript 語言的this物件一直是一個令人頭痛的問題,在物件方法中使用this,必須非常小心,箭頭函式”系結”this,很大程度上解決了這個困擾,我們不妨先看一個例子:

const team = {
  members:["Henry","Elyse"],
  teamName:"es6",
  teamSummary:function(){
    return this.members.map(function(member){
      return `${member}隸屬于${this.teamName}小組`;    // this不知道該指向誰了
    })
  }
}
console.log(team.teamSummary());//["Henry隸屬于undefined小組", "Elyse隸屬于undefined小組"] 

teamSummary函式里面又嵌了個函式,這導致內部的this的指向發生了錯亂,
那如何修改:

方法一、let self = this

const team = {
  members:["Henry","Elyse"],
  teamName:"es6",
  teamSummary:function(){
    let self = this;
    return this.members.map(function(member){
      return `${member}隸屬于${self.teamName}小組`;
    })
  }
}
console.log(team.teamSummary());//["Henry隸屬于es6小組", "Elyse隸屬于es6小組"] 

方法二、bind函式

const team = {
  members:["Henry","Elyse"],
  teamName:"es6",
  teamSummary:function(){
    return this.members.map(function(member){
      // this不知道該指向誰了
      return `${member}隸屬于${this.teamName}小組`;
    }.bind(this))
  }
}
console.log(team.teamSummary());//["Henry隸屬于es6小組", "Elyse隸屬于es6小組"] 

方法三、 箭頭函式

const team = {
  members:["Henry","Elyse"],
  teamName:"es6",
  teamSummary:function(){
    return this.members.map((member) => {
      // this指向的就是team物件
      return `${member}隸屬于${this.teamName}小組`;
    })
  }
}
console.log(team.teamSummary());//["Henry隸屬于es6小組", "Elyse隸屬于es6小組"] 

3.使用注意點

(1)函式體內的this物件,就是定義時所在的物件,而不是使用時所在的物件,

(2)不可以當作建構式,也就是說,不可以使用new命令,否則會拋出一個錯誤,

(3)不可以使用arguments物件,該物件在函式體內不存在,如果要用,可以用 rest 引數代替,

(4)不可以使用yield命令,因此箭頭函式不能用作 Generator 函式,

五、rest 引數

ES6 引入 rest 引數(形式為...變數名),用于獲取函式的多余引數,這樣就不需要使用arguments物件了,

rest 引數搭配的變數是一個陣列,該變數將多余的引數放入陣列中,
我們舉個例子:如何實作一個求和函式?

傳統寫法:

function addNumbers(a,b,c,d,e){
  var numbers = [a,b,c,d,e];
  return numbers.reduce((sum,number) => {
    return sum + number;
  },0)
 }
 console.log(addNumbers(1,2,3,4,5));//15 

ES6寫法:

 function addNumbers(...numbers){
  return numbers.reduce((sum,number) => {
    return sum + number;
  },0)
 }
 console.log(addNumbers(1,2,3,4,5));//15 

也可以與解構賦值組合使用

var array = [1,2,3,4,5,6];
var [a,b,...c] = array;
console.log(a);//1
console.log(b);//2
console.log(c);//[3, 4, 5, 6] 

rest 引數還可以與箭頭函式結合

const numbers = (...nums) => nums;
numbers(1, 2, 3, 4, 5)// [1,2,3,4,5] 

注意:①每個函式最多只能宣告一個rest引數,而且 rest引數必須是最后一個引數,否則報錯,

②rest引數不能用于物件字面量setter之中

let object = {
    set name(...value){   //報錯
        //執行一些邏輯
    }
} 

六、展開運算子

與剩余引數關聯最密切的就是擴展運算子,剩余引數允許你把多個獨立的引數合并到一個陣列中;而擴展運算子則允許將一個陣列分割,并將各個項作為分離的引數傳給函式,

當用在字串或陣列前面時稱為擴展運算子,個人覺得可以理解為rest引數的逆運算,用于將陣列或字串進行拆解,有些時候,函式不允許傳入陣列,此時使用展開運算子就很方便,不信的話,咱們看個例子:Math.max()方法,它接受任意數量的引數,并會回傳其中的最大值,

let value1 = 25,				
let value2 = 50;
console.log(Math.max(value1, value2));	//	50 

但若想處理陣列中的值,此時該如何找到最大值?Math.max()方法并不允許你傳入一個陣列,其實你可以像使用rest引數那樣在該陣列前添加...,并直接將其傳遞給 Math.max()

let values = [25,50,75,	100]
//等價于console.log(Math.max(25,50,75,100));
console.log(Math.max(...values));	//100 

擴展運算子還可以與其他引數混用

let values = [-25,-50,-75,-100]
console.log(Math.max(...values,0));	//0 

擴展運算子拆解字串與陣列

var array = [1,2,3,4,5];
console.log(...array);//1 2 3 4 5
var str = "String";
console.log(...str);//S t r i n g 

還可以實作拼接

var defaultColors = ["red","greed"];
var favoriteColors = ["orange","yellow"];
var fallColors = ["fire red","fall orange"];
console.log(["blue","green",...fallColors,...defaultColors,...favoriteColors]
//["blue", "green", "fire red", "fall orange", "red", "greed", "orange", "yellow"] 

七、解構賦值----更方便的資料訪問

ES6 新增了解構,這是將一個資料結構分解為更小的部分的程序,

1.解構為何有用?

在ES5及更早版本中,從物件或陣列中獲取資訊、并將特定資料存入本地變數,需要書寫許多并且相似的代碼,例如:

 var expense = {
   type: "es6",
   amount:"45"
 };
 var type = expense.type;
 var amount = expense.amount;
 console.log(type,amount); 

此代碼提取了expense物件的type與amount值,并將其存在同名的本地變數上,雖然 這段代碼看起來簡單,但想象一下若有大量變數需要處理,你就必須逐個為其賦值;并且若有一個嵌套的資料結構需要遍歷以尋找資訊,你可能會為了一點資料而挖掘整個結構,

這就是ES6為何要給物件與陣列添加解構,當把資料結構分解為更小的部分時,從中提取你要的資料會變得容易許多,

2.物件

上個例子中如果采用物件解構的方法,就很容易獲取expense物件的type與amount值,

const { type,amount } = expense;
console.log(type,amount); 

我們再來看個例子:

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

注意:你必須用圓括號包裹解構賦值陳述句,這是因為暴露的花括號會被決議為代碼塊陳述句,而塊陳述句不允許在賦值運算子(即等號)左側出現,圓括號標示了里面的花括號并不是塊陳述句、而應該被解釋為運算式,從而允許完成賦值操作,

默認值:
可以選擇性地定義一個默認值,以便在指定屬性不存在時使用該值,若要這么做,需要在 屬性名后面添加一個等號并指定默認值,就像這樣:

let node = {
  type: "Identifier",
  name: "foo"
};
let {
  type,
  name,
  value = https://www.cnblogs.com/xzsj/p/true
} = node;
console.log(type); //"Identifier" 
console.log(name); //	"foo" 
console.log(value); //	true 

嵌套物件解構:
使用類似于物件字面量的語法,可以深入到嵌套的物件結構中去提取你想要的資料,

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

本例中的解構模式使用了花括號,表示應當下行到node物件的loc屬性內部去尋找start屬性,

必須傳值的解構引數

function setCookie(name, value, {
  secure,
  path,
  domain,
  expires
}) {
  //	設定cookie的代碼 
}
  setCookie("type", "js");//報錯 

在此函式內,name與value引數是必需的,而secure、path、domain與expires則不是,默認情況下呼叫函式時未給引數解構傳值會拋出錯誤,像上例中如果setCookie不傳第三個引數,就會報錯,若解構引數是可選的,可以給解構的引數提供默認值來處理這種錯誤,

function setCookie(name, value, {
  secure,
  path,
  domain,
  expires
} = {}) {}
setCookie("type", "js");//不會報錯 

3.陣列

const names = ["Henry","Bucky","Emily"];
const [name1,name2,name3] = names;
console.log(name1,name2,name3);//Henry Bucky Emily
const [name,...rest] = names;//結合展開運算子
console.log(rest);//["Bucky", "Emily"] 

用{}解構回傳陣列個數

const {length} = names;
console.log(length);//3 

陣列解構也可以用于賦值背景關系,但不需要用小括號包裹運算式,這點跟物件解構的約定不同,

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

默認值:陣列解構賦值同樣允許在陣列任意位置指定默認值,當指定位置的項不存在、或其值為undefined,那么該默認值就會被使用,

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

與rest引數搭配

在ES5中常常使用concat()方法來克隆陣列,例如:

//在ES5中克隆陣列 
var colors = ["red", "green", "blue"];
var clonedColors = colors.concat();
console.log(clonedColors); //"[red,green,blue]" 

在ES6中,你可以使用剩余項的語法來達到同樣效果

//在ES6中克隆陣列 
let colors = ["red", "green", "blue"];
let [...clonedColors] = colors;
console.log(clonedColors); //[red,green,blue] 

接下我們看個例子:如何將陣列轉化為物件

const points = [
  [4,5],
  [10,1],
  [0,40]
];
//期望得到的資料格式如下,如何實作?
// [
//   {x:4,y:5},
//   {x:10,y:1},
//   {x:0,y:40}
// ]
let newPoints = points.map(pair => {
  const [x,y] = pair;
  return {x,y}
})
//還可以通過以下辦法,更為簡便
let newPoints = points.map(([x,y]) => {
  return {x,y}
})
console.log(newPoints); 

混合解構

const people = [
  {name:"Henry",age:20},
  {name:"Bucky",age:25},
  {name:"Emily",age:30}
];
//es5 寫法 
var age = people[0].age;
console.log(age);
//es6 解構
const [age] = people;
console.log(age);//第一次解構陣列 {name:"Henry",age:20}
const [{age}] = people;//再一次解構物件
console.log(age);//20 

4.注意點

當使用解構來配合var、let、const來宣告變數時,必須提供初始化程式(即等號右邊的值),下面的代碼都會因為缺失初始化程式而拋出語法錯誤:

var { type, name }; // 語法錯誤! 
let { type, name }; // 語法錯誤!
const { type, name }; // 語法錯誤! 

八、模板字串(template string)

模板字串是增強版的字串,用反引號(`)標識,它可以當作普通字串使用,也可以用來定義多行字串,或者在字串中嵌入變數,
模板字串中嵌入變數和函式,需要將變數名寫在${}之中,

let name = "Henry";
function makeUppercase(word){
  return word.toUpperCase();
}
let template = 
  `
  <h1>${makeUppercase('Hello')}, ${name}!</h1>//可以存放函式和變數
  <p>感謝大家收看我們的視頻, ES6為我們提供了很多遍歷好用的方法和語法!</p>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
  </ul>
  `;
document.getElementById('template').innerHTML = template; 

再舉個例子,作業中常用到ElementUI庫,在自定義一個彈出框時,使用模板字串就很方便:

 await this.$alert(
          `<p><strong>確認是否升級${
            this.lectureName
          }</strong><br>(若已存在講義套件,升級后請重新生成)</p>`,
          {
            dangerouslyUseHTMLString: true
          }
        ) 

九、Class 和傳統建構式有何區別

從概念上講,在 ES6 之前的 JS 中并沒有和其他面向物件語言那樣的“類”的概念,長時間里,人們把使用 new 關鍵字通過函式(也叫構造器)構造物件當做“類”來使用,由于 JS 不支持原生的類,而只是通過原型來模擬,各種模擬類的方式相對于傳統的面向物件方式來說非常混亂,尤其是處理當子類繼承父類、子類要呼叫父類的方法等等需求時,
ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念,作為物件的模板,通過class關鍵字,可以定義類,但是類只是基于原型的面向物件模式的語法糖

對比在傳統建構式和 ES6 中分別如何實作類:

//傳統建構式
function MathHandle(x,y){
  this.x=x;
  this.y=y;
}
MathHandle.prototype.add =function(){
  return this.x+this.y;
};
var m=new MathHandle(1,2);
console.log(m.add()) 
//class語法
class MathHandle {
 constructor(x,y){
  this.x=x;
  this.y=y;
}
 add(){
   return this.x+this.y;
  }
}
const m=new MathHandle(1,2);
console.log(m.add()) 

這兩者有什么聯系?其實這兩者本質是一樣的,只不過是語法糖寫法上有區別,所謂語法糖是指計算機語言中添加的某種語法,這種語法對語言的功能沒有影響,但是更方便程式員使用,比如這里class語法糖讓程式更加簡潔,有更高的可讀性,

typeof MathHandle //"function"
MathHandle===MathHandle.prototype.constructor //true 

對比在傳統建構式和 ES6 中分別如何實作繼承:

//傳統建構式繼承
function Animal() {
    this.eat = function () {
        alert('Animal eat')
    }
}
function Dog() {
    this.bark = function () {
        alert('Dog bark')
    }
}
Dog.prototype = new Animal()// 系結原型,實作繼承
var hashiqi = new Dog()
hashiqi.bark()//Dog bark
hashiqi.eat()//Animal eat 
//ES6繼承
class Animal {
    constructor(name) {
        this.name = name
    }
    eat() {
        alert(this.name + ' eat')
    }
}
class Dog extends Animal {
    constructor(name) {
        super(name) // 有extend就必須要有super,它代表父類的建構式,即Animal中的constructor
        this.name = name
    }
    say() {
        alert(this.name + ' say')
    }
}
const dog = new Dog('哈士奇')
dog.say()//哈士奇 say
dog.eat()//哈士奇 eat 

Class之間可以通過extends關鍵字實作繼承,這比ES5的通過修改原型鏈實作繼承,要清晰和方便很多,

Class 和傳統建構式有何區別

  • Class 在語法上更加貼合面向物件的寫法
  • Class 實作繼承更加易讀、易理解,對初學者更加友好
  • 本質還是語法糖,使用prototype

十、Promise的基本使用和原理

在JavaScript的世界中,所有代碼都是單執行緒執行的,由于這個“缺陷”,導致JavaScript的所有網路操作,瀏覽器事件,都必須是異步執行,Promise 是異步編程的一種解決方案,比傳統的解決方案(回呼函式和事件)更合理和更強大,

回呼地獄

ES6中的promise的出現給我們很好的解決了回呼地獄的問題,所謂的回呼地獄是指當太多的異步步驟需要一步一步執行,或者一個函式里有太多的異步操作,這時候就會產生大量嵌套的回呼,使代碼嵌套太深而難以閱讀和維護,ES6認識到了這點問題,現在promise的使用,完美解決了這個問題,

Promise原理

一旦狀態改變,就不會再變,任何時候都可以得到這個結果,Promise物件的狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected,promise 物件初始化狀態為 pending ;當呼叫resolve(成功),會由pending => fulfilled ;當呼叫reject(失敗),會由pending => rejected,具體流程見下圖:

Promise原理

Promise的使用流程

  1. new Promise一個實體,而且要 return
  2. new Promise 時要傳入函式,函式有resolve reject 兩個引數
  3. 成功時執行 resolve,失敗時執行reject
  4. then 監聽結果
function loadImg(src){
   const promise=new Promise(function(resolve,reject){
     var img=document.createElement('img')
     img.onload=function(){
        resolve(img)
   }
     img.onerror=function(){
        reject()
   }
    img.src=https://www.cnblogs.com/xzsj/p/src
 })
  return promise//回傳一個promise實體
}
var src="https://img.uj5u.com/2021/04/01/232016012025359.png"
var result=loadImg(src)
result.then(function(img){
    console.log(img.width)//resolved(成功)時候的回呼函式
},function(){
    console.log("failed")//rejected(失敗)時候的回呼函式
})
result.then(function(img){
    console.log(img.height)
}) 

promise會讓代碼變得更容易維護,像寫同步代碼一樣寫異步代碼,同時業務邏輯也更易懂,

十一、Iterator 和 for...of 回圈

JavaScript 原有的表示“集合”的資料結構,主要是陣列(Array)和物件(Object),ES6 又添加了Map和Set,這樣就需要一種統一的介面機制,來處理所有不同的資料結構,遍歷器(Iterator)就是這樣一種機制,它是一種介面,為各種不同的資料結構提供統一的訪問機制,任何資料結構只要部署 Iterator 介面,就可以完成遍歷操作(即依次處理該資料結構的所有成員)

1.Iterator的作用:

  • 為各種資料結構,提供一個統一的、簡便的訪問介面;
  • 使得資料結構的成員能夠按某種次序排列
  • ES6創造了一種新的遍歷命令for...of回圈,Iterator介面主要供for...of消費,

2.原生具備iterator介面的資料(可用for of遍歷)

  • Array
  • set容器
  • map容器
  • String
  • 函式的 arguments 物件
  • NodeList 物件
let arr3 = [1, 2, 'kobe', true];
for(let i of arr3){
   console.log(i); // 1 2 kobe true
} 
let str = 'abcd';
for(let item of str){
   console.log(item); // a b c d
} 
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
  console.log(e);
}
// Gecko
// Trident
// Webkit 

3.幾種遍歷方式比較

  • for of 回圈不僅支持陣列、大多數偽陣列物件,也支持字串遍歷,此外還支持 Map 和 Set 物件遍歷,
  • for in回圈可以遍歷字串、物件、陣列,不能遍歷Set/Map
  • forEach 回圈不能遍歷字串、物件,可以遍歷Set/Map

十二、ES6模塊化

ES6 在語言標準的層面上,實作了模塊功能,而且實作得相當簡單,旨在成為瀏覽器和服務器通用的模塊解決方案,其模塊功能主要由兩個命令構成:export和import,export命令用于規定模塊的對外介面,import命令用于輸入其他模塊提供的功能,

/** 定義模塊 math.js **/
var basicNum = 0;
var add = function (a, b) {
    return a + b;
};
export { basicNum, add };
/** 參考模塊 **/
import { basicNum, add } from './math';
function test(ele) {
    ele.textContent = add(99 + basicNum);
} 

如上例所示,使用import命令的時候,用戶需要知道所要加載的變數名或函式名,否則無法加載,為了給用戶提供方便,讓他們不用閱讀檔案就能加載模塊,就要用到export default命令,為模塊指定默認輸出,

// export-default.js
export default function () {
  console.log('foo');
} 

上面代碼是一個模塊檔案export-default.js,它的默認輸出是一個函式,
其他模塊加載該模塊時,import命令可以為該匿名函式指定任意名字,

// import-default.js
import customName from './export-default';
customName(); // 'foo' 

上面代碼的import命令,可以用任意名稱指向export-default.js輸出的方法,這時就不需要知道原模塊輸出的函式名,需要注意的是,這時import命令后面,不使用大括號,

后記

如需前端指導、前端資料、Java指導和 Java 資料的請聯系本人,感謝您的支持,

WECHAT:xzsj07
備注:加好友請注明來源,

作者:浪里行舟
來源:github
地址:ES6核心特性
著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/270865.html

標籤:JavaScript

上一篇:利用pdf.js在線展示PDF檔案

下一篇:「免費開源」基于Vue和Quasar的前端SPA專案crudapi后臺管理系統實戰之自定義組件(四)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more