ES6常用的語法總結
1、let 和 const
相同點:不存在變數提升,不能重複宣告,在當前塊內有效 。
不同點:let可以重複賦值,const不能再賦值。
(關於const:const宣告時必須初始化賦值,不能重複賦值的意思是宣告變數指向的那個記憶體地址所儲存的資料不得改動。簡單資料型別(數字、字串、布林值)的值就儲存在變數指向的那個記憶體地址,因此值不可改變,而複雜資料型別(主要是物件和陣列)儲存的只是一個指向實際資料的指標,因此物件的內容可以改變)
2、字串新增的方法
(1) 字串模版:
// 支援字串換行
let str1 = `<div>
<span></span>
<span>`
// 支援字串插入變數值
let str2 = `aaa ${str1} bbb`
(2) includes(str, index)
檢測字串中是否含有指定文字,返回true或false
const str1 = 'a1b2c3d4'
str1.includes('c3') // true
str1.includes('e') // false
(3) startsWith(str, index)/endsWith(str, index)
檢測是否以指定字串開始/結束,返回true或false
const str1 = 'a1b2c3d4'
str1.startsWith('c3') // true
str1.startsWith('c3', 6) // false
3、函式
(1) 預設引數
定義函式時給引數設定預設值,如果呼叫函式時沒有傳引數,則用預設值
function fun1 (a=12, b='ssa') {
return a + b
}
fun1() // '12ssa'
fun1(3, 10) // 13
(2)箭頭函式
普通函式的簡寫模式(與普通函式有一定的差異)
fun1 (a, b) => {
return a + b
}
// 當只有1個引數,並且返回值只有一行時,可以省略括號和return
fun1 a => a +5
箭頭函式與普通函式的區別:
-> 普通函式:
函式內部this指向呼叫者
- 當作為全域性函式被呼叫時,this指向全域性物件
- 當作為物件中的方法被呼叫時,this指向該物件
- 當作為建構函式時,this指向建構函式new出來的物件
同時還可以通過call,apply,bind的呼叫方式改變this的指向
-> 箭頭函式
箭頭函式沒有this (箭頭函式中,this屬於詞法作用域,直接由上下文確定,對於普通函式中指向不定的this,箭頭函式中處理this無疑更加簡單),因此:
- 箭頭函式沒有arguments (可以用rest引數替代)
- 箭頭函式沒有super
- 箭頭函式不能改變this的指向
- 箭頭函式沒有new.target繫結
- 箭頭函式沒有原型,不能使用new
- 不支援重複的命名引數
// 陣列排序
const arr = [4, 15, 5, 7, 24]
const s = arr.sort((a, b) => a - b)
(3)尾調的用優化
尾呼叫是指在函式return的時候呼叫一個新的函式,由於尾呼叫的實現需要儲存到記憶體中,在一個迴圈體中,如果存在函式的尾呼叫,可能會導致記憶體爆滿或溢位。
ES6中,引擎會幫你做好尾呼叫的優化工作,你不需要自己優化,但需要滿足下面3個要求:
1)、函式不是閉包
2)、尾呼叫是函式最後一條語句
3)、尾呼叫結果作為函式返回
尾呼叫實際用途——遞迴函式優化
在ES5時代,我們不推薦使用遞迴,因為遞迴會影響效能。
但是有了尾呼叫優化之後,遞迴函式的效能有了提升。
//新型尾優化寫法
"use strict"
function a(n, p = 1) {
if(n <= 1) {
return 1 * p
}
let s = n * p
return a(n - 1, s)
}
//求 1 x 2 x 3的階乘
let sum = a(3)
console.log(sum) // 6
4、陣列
ES6陣列新增的方法: find()、findIndex()、fill()、copyWithin()
(1) find():傳入一個回撥函式,找到陣列中符合當前搜尋規則的第一個元素,返回它,並且終止搜尋。
const arr = [1, "2", 3, 3, "2"]
arr.find(n => typeof n === "number") // 1
(2) findIndex():傳入一個回撥函式,找到陣列中符合當前搜尋規則的第一個元素,返回它的下標,終止搜尋。
const arr = [1, "2", 3, 3, "2"]
arr.findIndex(n => typeof n === "number") // 0
(3) fill():用新元素替換掉陣列內的元素,可以指定替換下標範圍。(對原陣列修改)
arr.fill(value, start, end)
let a = [1,2,3,4,5]
a.fill('a', 2) // a = [1,2,'a','a','a']
let b = [1,2,3,4,5]
b.fill('x', 1,3) // b = [1,'x','x',4, 5]
(4) copyWithin():選擇陣列的某個下標,從該位置開始複製陣列元素,預設從0開始複製。也可以指定要複製的元素範圍。
arr.copyWithin(target, start, end)
const arr = [1, 2, 3, 4, 5]
console.log(arr.copyWithin(3)) // [1,2,3,1,2] 從下標為3的元素開始,複製陣列,所以4, 5被替換成1, 2
const arr1 = [1, 2, 3, 4, 5]
console.log(arr1.copyWithin(3, 1)) // [1,2,3,2,3] 從下標為3的元素開始,複製陣列,指定複製的第一個元素下標為1,所以4, 5被替換成2, 3
const arr2 = [1, 2, 3, 4, 5]
console.log(arr2.copyWithin(3, 1, 2)) // [1,2,3,2,5] 從下標為3的元素開始,複製陣列,指定複製的第一個元素下標為1,結束位置為2,所以4被替換成2
5、物件方法Object.assign()
方法用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件。它將返回目標物件。
(如果物件有存在同樣的屬性,後面物件的屬性覆蓋前面的)
Object.assign(target, ...sources)
const obj1 = {a: 1 ,b: 1 ,c: 1}
const obj2 = {c: 2 ,d: 2}
const obj3 = {c: 3 ,e: 3}
objRe1 = Object.assign(o1, o2) // => {a: 1, b: 1, c: 2, d: 2}
objRe2 = Object.assign(o2, o1) // => {c: 1, d: 2, a: 1, b: 1}
objRe3 = Object.assign(o1, o2, o3) // => {a: 1, b: 1, c: 3, d: 2, e:3}
6、 Map 和 Set
Set:
Set與Arrar一樣都是儲存多值的容器,兩者可以互相轉換,但是在使用場景上有區別:
- Set是有序列表,值不可重複(可以利用這個特性實現對一個數組的去重);
- Set的has比Array的IndexOf方法效率更好;
- Set通過delete方法刪除某個值,而Array只能通過splice(Set刪除方法更好);
Set的操作方法:
let set1 = new Set() // 建立一個Set
// Set => Array
let arr1 = Array.from(set1) // Set => Array
let arr2 = [...set1] // Set => Array
// Array => Set
let set1 = new Set(arr1)
// 先將Set轉為陣列,用陣列的方法操作完成後,再轉回為Set
let set1 = new Set([...set1].map((x) => x = x * 2))
let set1 = new Set([...set1].filter((x) => x > 2))
set1.constructor === Set // 例項屬性(繼承自Set)
// 操作方法
set1.size() // 獲取長度
set1.add(1) // 新增
set1.delete(1) // 刪除
set1.has(1) // 判斷是否包含這個值
set1.clear() // 清空所有值
// 獲取用於遍歷的成員方法(Set的遍歷順序就是插入順序)
set.keys() // 返回鍵名的遍歷器
set.values() // 返回鍵值得遍歷器
set.entries() // 返回鍵值對的遍歷器
set.forEach() // 迴圈遍歷每個值(和Array的方法一致)
for (let key of set.keys()) { }
for (let val of set.values()) {}
for (let entry of set.entries()) {}
Map:
Map集合常被用來獲取已存的資訊,與Object類似:
- Map是值-值 ; Object是字串
- Map的鍵是任意型別 ; Object鍵為string型別
- Map.size可以獲取尺寸 ; 手動計算Object尺寸
- Map的排序是插入順序 ; Object不是
- Object有原型,所以對映中有一些預設的鍵。可以理解為Map=Object.create(null)
Map的操作方法:
let map1 = new Map()
// 例項屬性(繼承自Map)
map1.constructor === Map
map1.size
// 操作方法
map1.set(1,2)
map1.get(1)
map1.delete(1)
map1.has(1)
map1.clear()
// 遍歷方法
map1.keys()
map1.values()
map1.entries()
map1.forEach()
// Map和陣列的轉換
map1 = new Map([['key','val'],[2,1]]) // 要求雙成員陣列
let arr1 = [...map1]
// 值得注意的是Map的鍵是跟記憶體繫結的
map1.set([1], 's')
map1.get([1])
let arr1 = [1]
let arr2 = [1]
map1.set(arr1, 's')
map1.get(arr1)
map1.set(arr2, 's')
map1.get(arr2)
7、迭代器
(1) entries() 返回迭代器:返回鍵值對
//陣列
const arr = ['a', 'b', 'c'];
for(let v of arr.entries()) {
console.log(v)
}
// [0, 'a'] [1, 'b'] [2, 'c']
//Set
const arr = new Set(['a', 'b', 'c']);
for(let v of arr.entries()) {
console.log(v)
}
// ['a', 'a'] ['b', 'b'] ['c', 'c']
//Map
const arr = new Map();
arr.set('a', 'a1');
arr.set('b', 'b1');
for(let v of arr.entries()) {
console.log(v)
}
// ['a', 'a1'] ['b', 'b1']
(2) values() 返回迭代器:返回鍵值對的value
//陣列
const arr = ['a', 'b', 'c'];
for(let v of arr.values()) {
console.log(v)
}
//'a' 'b' 'c'
//Set
const arr = new Set(['a', 'b', 'c']);
for(let v of arr.values()) {
console.log(v)
}
// 'a' 'b' 'c'
//Map
const arr = new Map();
arr.set('a', 'a1');
arr.set('b', 'b1');
for(let v of arr.values()) {
console.log(v)
}
// 'a1' 'b1'
(3) keys() 返回迭代器:返回鍵值對的key
//陣列
const arr = ['a', 'b', 'c'];
for(let v of arr.keys()) {
console.log(v)
}
// 0 1 2
//Set
const arr = new Set(['a', 'b', 'c']);
for(let v of arr.keys()) {
console.log(v)
}
// 'a' 'b' 'c'
//Map
const arr = new Map();
arr.set('a', 'a1');
arr.set('b', 'b1');
for(let v of arr.keys()) {
console.log(v)
}
// 'a' 'b'
雖然上面列舉了3種內建的迭代器方法,但是不同集合的型別還有自己預設的迭代器,在for of中,陣列和Set的預設迭代器是values(),Map的預設迭代器是entries()。
for of迴圈解構
物件本身不支援迭代,但是我們可以自己新增一個生成器,返回一個key,value的迭代器,然後使用for of迴圈解構key和value。
const obj = {
a: 1,
b: 2,
*[Symbol.iterator]() {
for(let i in obj) {
yield [i, obj[i]]
}
}
}
for(let [key, value] of obj) {
console.log(key, value)
}
// 'a' 1, 'b' 2
字串迭代器
const str = 'abc';
for(let v of str) {
console.log(v)
}
// 'a' 'b' 'c'