1. 程式人生 > 其它 >ECMAScript 6學習

ECMAScript 6學習

es6新特性

let、const和var的區別⭐

1. 塊級作用域{}
Es5中作用域有:全域性作用域、函式作用域,沒有塊級作用域的概念
Es6中新增塊級作用域。塊級作用域用{}包括,if和for語句裡面的{}也屬於塊作用域

2. var沒有塊的概念,可以跨塊訪問,不能跨函式訪問
3. let只能在塊作用域訪問,不能跨塊或跨函式訪問
4. const用來定義常量,使用時必須初始化(即必須賦值,只能在塊作用域訪問,且不能更改)
const定義的物件屬性是否可以改變?因為物件是引用型別,物件中儲存的僅是物件的指標,const保證指標不發生改變,修改物件屬性不會改變物件指標

陣列方法⭐

forEach()、some()、filter()、map()、reduce()、every()、find()

forEach()

var arr = [1, 2, 3];
arr.forEach(function (value, index, array) {
    console.log('每個陣列元素' + value);
    console.log('每個陣列元素的索引號' + index);
    console.log('陣列本身' + array);
})

some()

// 只要有一個滿足就行
var arr = [10,20,30,40,50];
var flag = arr.some(function(value){
    return value > 20;  // 在 some 裡面遇到 return true 就會終止遍歷 效率更高
});// true 

every()

// 要所有的滿足才可以
var arr = [10,20,30,40,50];
let res = arr.every(item => item > 20)   // false

filter()

var arr = [12, 66, 4, 55, 22, 11];
var newArr = arr.filter(function (value, index) {
    return value % 2 === 0;  // filter 裡面 return 不會終止迭代,要有返回值,返回一個新陣列
});
// [66,55,22]

map()

var numbers = [1,2,3]
var double = numbers.map(number => number * 2)   // 要有返回值,返回一個新陣列
console.log(double)  // [2,4,6]

reduce()

// reduce(function(sum,number){...},0)要有兩個引數,第一個引數一定要初始化
// 代替map做一些簡單的運算
// 將一個物件陣列中的某些屬性的值抽出來,組成一個新的陣列
var arr = [1,2,3]
var res = arr.reduce((sum,number)=>{
    return sum + number
},3)  // 4,5,6

find()

// 只會找到第一個符合的資料,找到之後就會直接返回
let aim = 1
let arr = [1,2,3]
let res = arr.find(item => item === aim)

for...of迴圈

for...of迴圈是最新新增到 JavaScript 迴圈系列中的迴圈。
它結合了其兄弟迴圈形式 for 迴圈和 for...in 迴圈的優勢,可以迴圈任何可迭代(也就是遵守可迭代協議)型別的資料,可以隨時停止或退出迴圈。預設情況下,包含以下資料型別:StringArrayMapSet預設情況下,物件不可迭代

for...of遍歷的是鍵值,for...in遍歷的是鍵名
for...of不能對屬性值進行修改,forEach()可以

不用擔心向物件中新增新的屬性。for...of 迴圈將只迴圈訪問物件中的值。

Array.prototype.decimalfy = function() {
  for (i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}

rest引數

ES6引入rest引數,用於獲取函式的實參,用來代替arguments物件,它不僅將額外的引數表示為陣列,還解決了arguments物件的許多問題。

arguments物件用於訪問未知或可變的函式引數,即使arguments使用length屬性和方括號,它不是一個真正的JavaScript陣列。arguments物件不能使用其他JavaScript陣列方法,如pop,push,slice等。

你可以將rest引數定義為…theArgs或… args。如果最後命名的函式引數以…(三個點)作為字首,那麼它將成為函式的rest引數。

function add(...theArgs){
    var result = 0;
    for(let i=0;i<theArgs.length;i++){
        result = result + theArgs[i];
    }
    return result;
}
var r = add(6,9,3,2);
console.log(r);

rest引數是JavaScript陣列,可以對rest引數theArgs執行諸如push,pop等操作

function add(...theArgs){
    theArgs.push(10);
    var result = 0;
    for(let i=0;i<theArgs.length;i++){
        result = result + theArgs[i];
    }
    var lastItem  = theArgs.pop();
    console.log(lastItem);
    return result;
}

JavaScript函式的rest引數也可以與其他引數一起工作

function add(num1, num2, ...theArgs){  // rest引數必須是最後一個正式引數。
    console.log(num1);
    console.log(num2);
    console.log(theArgs.length);
}
var r = add(6,9,3,2);  // 前兩個引數不會成為rest引數陣列的一部分

箭頭函式⭐

使用方法

() => {}

和普通函式的區別

① 普通函式可以是函式宣告或者函式表示式, 但是箭頭函式始終都是表示式, 全程是箭頭函式表示式, 因此僅在表示式有效時才能使用

② 普通函式的this指向呼叫其函式的物件,而箭頭函式的this始終指向函式宣告時所在作用域下的this的值,無法被call改變

③ 箭頭函式不能作為建構函式例項化物件

④ 箭頭函式不能使用arguments變數,但是可以使用...rest

模組化es6⭐

ES6模組化規範中定義

② 匯入模組成員使用 import 關鍵字

③ 暴露模組成員使用 export 關鍵字

CommonJS

② 模組成員匯出:(ma zou) module.exports 和 exports

③ 模組成員匯入:require('模組識別符號')

和CommonJs的異同

異:
① CommonJS 模組是執行時載入,ES6 模組是編譯時輸出介面
    執行時載入: CommonJS 模組就是物件;即在輸入時是先載入整個模組,生成一個物件,然後再從這個物件上面讀取方法,這種載入稱為“執行時載入”。
    編譯時載入: ES6 模組不是物件,即在import時可以指定載入某個輸出值,而不是載入整個模組,這種載入稱為“編譯時載入”
② CommonJS 模組輸出的是一個值的拷貝,ES6 模組輸出的是值的引用
    CommonJS 是對模組的淺拷貝,ES6 Module 是對模組的引用,即ES6 Module只存只讀,不能改變其值,具體點就是指標指向不能變,類似 const。
    
同:
CommonJS和ES6 Module都可以對引入的物件進行賦值,即對物件內部屬性的值進行改變。

模板字串⭐

在ES6之前,將字串連線到一起的方法是+或者concat()方法

模板字串本質上是包含嵌入式表示式的字串字面量.

模板字面量用倒引號 ( `` )(而不是單引號 ( '' ) 或雙引號( "" ))表示,可以包含用 ${expression} 表示的佔位符

類class⭐

ES6中添加了對類的支援,引入了class關鍵字。JS本身就是面向物件,ES6中提供的類實際上只是JS原型模式包裝。

以前編寫一個建構函式(類)
function Pad(color){
	this.color = color;
}
現在的寫法跟Java更接近了
class Iphone{
	constructor(color, size){
	this.color = color;
	this.size = size;
	}
	playgame(){
		//.............
	}
	toString(){
		return `這臺手機的顏色是${this.color} 螢幕大小是${this.size}`;
	}
}
我們定義了一個類,名字叫Iphone
通過類生成一個例項:
var iphone = new Iphone("白色", 5);其中constructor被稱之為構造方法,在我們new 一個物件的時候,自動被呼叫不過本質上,JS依然使用了原型來實現,也就是說,這不過是一個新的寫法而已 跟以前的建構函式沒有區別。要注意的是,使用了class來定義類,必須先定義再使用

解構⭐

解構:從陣列和物件提取值並賦值給獨特的變數

陣列解構

const Web = ['html', 'css', 'javascript']
let [tool1, tool2, tool3] = Web

物件解構

const liMing = {
    name: 'liMing',
    age: '22',
    tell: function(){
        console.log(`I am liMing`)
    }
}

let {name, age, tell} = liMing

物件字面量簡寫法

如果屬性名稱和所分配的變數名稱一樣,那麼就可以從物件屬性中刪掉這些重複的變數名稱

type: type   =>  type

Promise物件⭐

Promise出現的目的是解決Node.js非同步程式設計中回撥地獄的問題。
resolve => .then 成功  reject => .catch 失敗

function p1(){
	return new Promise(function(resolve,reject){
		// 假如讀取多個檔案
		fs.readFile('./1.txt', 'utf-8', (err, doc) => {
        	if (err) {
            	reject(err);
       		} else {
            	resolve(doc);
        	}
    	})
	})
}
function p2()....../2.txt

p1().then(r1=>{
    console.log(r1);
    // return一個promise物件,那麼下一個then當中拿到的結果就是在上一個then裡面return的promise物件的結果
	return p2();
})
	.then((r2) => {
        console.log(r2);
    })
// promise 語法無巢狀,更易維護,解決回撥地獄問題

then的第二個引數和catch捕獲錯誤資訊的時候會就近原則,如果是promise內部報錯,reject丟擲錯誤後,then的第二個引數和catch方法都存在的情況下,只有then的第二個引數能捕獲到,如果then的第二個引數不存在,則catch方法會捕獲到。
Promise.resolve('foo')
// 等價於
new Promise(resolve => resolve('foo'))

promise.all()

可以將多個Promise例項包裝成一個新的Promise例項。成功和失敗的返回值是不同的,成功的時候返回的是一個結果陣列,而失敗的時候返回最先被reject失敗狀態的值。

let p1 = new Promise((resolve,reject) => {
    resolve("成功了");
})
let p2 = new Promise((resolve,reject) => {
    resolve("success");	
})
let p3 = new Promise((resolve,reject) => {
    reject("fail");	
})
 
Promise.all([p1,p2]).then((result) => {
    console.log(result)     // ['成功了','success']
}).catch((error) => {
    console.log(error)
})
 
Promise.all([p1,p3,p2]).then((result) => {
    console.log(result)
}).catch((error) => {
    console.log(error)      // 'fail'
})

有些時候我們做一個操作可能得同時需要不同的介面返回的資料,這時我們就可以使用Promise.all

Promise.all獲得的成功結果的數組裡面的資料順序和Promise.all接收到的陣列順序是一致的,即p1的結果在前,即便p1的結果獲取的比p2要晚。

promise.all實現

let promiseAll = (promises) => {
  return new Promise((resolve, reject) => {
    // 判斷是否為陣列
    if (!(promises instanceof Array)) {
      // 丟擲錯誤
      throw new TypeError('promises must be an Array')
    }
    let len = promises.length         // promise物件陣列長度
    let resolveCount = 0			  // 當前遍歷到第一個,最後一個時返回正確的陣列
    let resolveArr = new Array(len)   // 成功輸入的陣列,與遍歷的promise陣列長度一致
    for (let i = 0; i < len; i++) {
      (function(i){  			      // 用上閉包更好
        promises[i].then(data => {
          resolveCount++
          resolveArr[i] = data
          // 如果都是成功的,只有到最後一個才會返回正確的陣列
          if (resolveCount === len) {
            return resolve(resolveArr)
          }
          // 一旦有錯誤就返回該項錯誤,並終止遍歷該promise物件陣列,實現失敗的時候返回最先被reject失敗狀態的值
        }).catch(err => {
          return reject(err)
        })
      })(i)
    }
  })
}

promiseAll([p1, p2, p3]).then(data => {
  console.log(data);
}).catch(res => {
  console.log(res);
})

promise.race()

Promise.race([p1,p2,p3])裡面哪個結果獲得快,就返回哪個結果,不管結果本身是成功還是失敗狀態。

有時我們比如說有好幾個伺服器的好幾個介面都提供同樣的服務,我們不知道哪個介面更快,就可以使用Promise.race,哪個介面的資料先回來我們就用哪個介面的資料。

async/await配合使用

Set集合和Map集合

兩者都集合實現了iterator介面,所以可以使用...擴充套件運算子和for...of進行遍歷

set:
  set是ES6提供的一種新的資料結構,類似於陣列,但是成員的值是唯一的沒有重複的,接受的引數是一個數組 方法有:
  add():新增
  delete():刪除
  size:長度
  has():查詢
  clear:清除所有
map:
  map類似於物件,也是鍵值對的集合, 但是“鍵”的範圍不限於字串,各種型別的值(包括物件)都可以當作鍵 方法有:
  set():設定
  get():獲取
  delete():刪除
  has():查詢
  clear():清除所有

擴充套件運算子...⭐

用三個連續的點 (...) 表示,能夠將字面量物件展開為多個元素,可使用者陣列的合併、克隆和將偽陣列轉為真正的陣列(多個dom物件)

函式引數的預設值設定

ES6允許給函式引數賦初始值,可與...擴充套件運算子一起使用

function add(a, b, c=10){ // 具有預設值的引數,一般位置要靠後
    return a + b + c
}
console.log(add(1,2,))

Symbol

ES6引入了一種新的原始資料型別Symbol,表示獨一無二的值。它是JavaScript語言的第7種資料型別,是一個類似字串的資料型別l

建立Symbol:

  1. 通過let s2 = Symbol('張三') 的方式建立Symbol,'張三’作為Symbol描述,作用相當於註釋,這種方式建立的Symbol,即使傳入的描述一致,但實際返回的值是不同的
// 建立Symbol
let s = Symbol()
console.log(s,typeof s) // Symbol() "symbol"

let s2 = Symbol('張三') // '張三'作為Symbol描述,作用相當於註釋
let s3 = Symbol('張三') // 即使傳入的描述一致,但實際返回的值是不同的
console.log(s2 === s3) // false
  1. 通過Symbol.for()建立Symbol,這種方式建立Symbol,傳入的描述一致,實際返回的值也一致,可以得到唯一的Symbol值

    // Symbol.for建立Symbol
    let s4 = Symbol.for('張三')
    let s5 = Symbol.for('張三')
    console.log(s4 === s5) // true
    

迭代器iterator(A te wei te)

迭代器(iterator)是一種介面,為各種不同的資料結構提供統一的訪問機制。任何資料結構只要部署iterator介面,就可以完成遍歷操作

字串API

在ES6中,為字串擴充套件了幾個新的API

  • includes(“xxx”):返回布林值,表示是否包含xxx
  • startsWith(“xxx”):返回布林值,表示是否以xxx開頭
  • endsWith(“xxx”):返回布林值,表示是否以xxx結尾
let str = "Hello Javascript";
console.log(str, "中是否包含 hello ==>", str.includes("hello"));
console.log(str, "中是否包含 hi ==>", str.includes("hi"));

console.log(str, "中是否以 h 開頭==>", str.startsWith("h"));
console.log(str, "中是否以 a 開頭==>", str.includes("a"));

console.log(str, "中是否以 a 結尾==>", str.includes("a"));
console.log(str, "中是否以 t 結尾==>", str.includes("t"));