@
一、ES6簡介
ES:ECMAScript;隨后的數字表示版本,ES6表示ES5之后的版本。
為什么使用ES6:越高版本的標准代表着js語言更加完善,本身功能更加強大。
比如ES6之前js本身的一些問題:
- 變量提升特性增加了程序運行時的不可預測性
- 語法過於松散
二、ES6新增語法
1. let關鍵字
ES6中新增了用於聲明變量的關鍵字
- let聲明的變量沒有變量提升
console.log(a); // a is not defined
let a = 20;
- let聲明的變量只在所處於的塊級有效
if (true) {
let a = 10;
var b = 20;
console.log(a); //10
console.log(b); //20
if(true){
let c = 30;
console.log(c);//30
}
console.log(c)// c is not defined
}
console.log(a) // a is not defined
console.log(b); //20
注意: 使用let關鍵字聲明的變量才具有塊級作用域,使用var聲明的變量不具備塊級作用域特性。
- 防止循環變量變成全局變量
/*
for (var i = 0; i < 2; i++) {}
console.log(i); // 2
*/
for (let i = 0; i < 2; i++) {}
console.log(i); // i is not defined
//eg 面試題
var arr = [];
for (let i = 0; i < 2; i++) {//如果 var i, 則不會產生單獨的塊級作用域,循環完后調用數組成員,輸出的都是2
arr[i] = function() {
console.log(i);
}
}
arr[0]();//0
arr[1]();//1
此題的關鍵點在於每次循環都會產生一個塊級作用域
,每個塊級作用域中的變量都是不同的,
函數執行時輸出的是自己上一級(循環產生的塊級作用域)作用域下的i值.
- 使用let關鍵字聲明的變量具有暫時性死區特性
利用let聲明的變量會綁定在這個塊級作用域,不會受外界的影響
var num = 10
if (true) {
console.log(num);// Cannot access 'num' before initialization , 初始化前無法訪問“num”
let num = 20;
}
2. const關鍵字
作用:聲明常量,常量就是值(內存地址)不能變化的量。
- const聲明的常量具有塊級作用域
if (true) {
const a = 10;
if (true) {
const a = 20;
console.log(a);//20
}
console.log(a);//10
}
console.log(a);//a is not defined
- 使用const關鍵字聲明的常量必須賦初始值
//const PI; //報錯: Missing initializer in const declaration ,常量聲明中缺少初始值設定項
const PI = 3.14;
- 常量聲明后值內存地址不可更改
如果是基本數據類型,不能更改值,如果是復雜數據類型,不能更改地址值
//簡單數據類型常量
const PI = 3.14;
PI = 100; // Assignment to constant variable.
//復雜數據類型常量 的內部可以修改
const ary = [100, 200];
//對內存地址內部修改,地址本身沒有修改,所以不會報錯
ary[0] = 'a';
ary[1] = 'b';
console.log(ary); // ['a', 'b'];
ary = ['a', 'b']; //修改了地址,報錯: Assignment to constant variable.
var、let、const關鍵字總結
var | let | const | |
---|---|---|---|
被定義變量的作用域 | 函數級作用域 | 塊級作用域 | 塊級作用域 |
變量特性 | 變量提升 | 不存在變量提升 | 不存在變量提升 |
變量值 | 值可更改 | 值可更改 | 值不可更改 |
3. 解構賦值
ES6中允許從數組或對象中提取值,按照對應位置,對變量實現解構賦值。
//基本語法
let [name1, name2, name3...] = ArrayName;
let {name4, name5, name6...} = ObjectName;
/*注意:
1. 聲明變量的關鍵字不一定是let
2. [name1 , name2, name3] 不是一個數組,其中的name表示變量名字, 整體表示一串變量,{name4, name5, name6} 也是同理
3. 數組解構用中括號包裹,多個變量用逗號隔開,對象解構用花括號包裹,多個變量用逗號隔開
數組解構
數組解構允許我們按照一一對應的關系從數組中提取值 然后將值賦值給變量
let ary = [1, 2, 3];
let [a, b, c, d, e] = ary;
console.log(a)//1
console.log(b)//2
console.log(c)//3
//如果解構不成功,變量的值為undefined。
console.log(d)//undefined
console.log(e)//undefined
對象解構
對象解構允許我們使用變量的名字匹配對象的屬性 匹配成功 將對象屬性的值賦值給變量,
利用解構賦值能夠讓我們方便的去取對象中的屬性跟方法
- 方式一
let person = {name: 'lisi', age: 30, sex: '男'};
let {name, age, abc} = person;
console.log(name)//'lisi'
console.log(age)//30
//若變量名匹配不到對象成員,則為undefined
console.log(abc)//undefined
- 方式二
//為了解決變量名匹配失敗的問題,有如下寫法
let {name: myName, age: myAge} = person; // myName myAge 屬於別名
console.log(myName); // 'zhangsan'
console.log(myAge); // 20
/*注意:
name: myName
冒號前面用來匹配對象成員,后面表示變量
*/
4. 箭頭函數
ES6中新增的定義函數的方式,如下
//箭頭函數是用來簡化函數定義語法的
(形參) => {函數體};
//上述表達式有返回值,通常定義一個變量或常量來接收函數
const fn = () => {};//代表把一個函數賦值給fn
fn();
- 函數體中只有一句代碼,且代碼的執行結果就是返回值,可以省略大括號
const sum = (n1, n2) => n1 + n2;
const result = sum(10, 20);
console.log(result)//30
- 如果形參只有一個,可以省略小括號
const fn = v => {
alert(v);
}
fn(20)
- 箭頭函數不綁定this關鍵字,箭頭函數中的this,箭頭函數中的this指向定義該函數的父級作用域中的this指向
const obj = { name: '張三'}
function fn () {
console.log(this);//this 指向 是obj對象
return () => {
console.log(this);//this 指向 的是箭頭函數定義的位置,那么這個箭頭函數定義在fn里面,而這個fn指向是的obj對象,所以這個this也指向是obj對象
}
}
//通過call()調用fn函數,並指定函數中的this指向 obj對象
const resFn = fn.call(obj);
resFn();
- 箭頭函數被定義在對象中時,對象不產生作用域,箭頭函數中的this指向定義該對象的作用域中的this
var age = 100;
var obj = {
age: 20,
say: () => {
alert(this.age)
}
}
obj.say();//箭頭函數this指向的是被聲明的作用域里面,而對象沒有作用域的,所以箭頭函數雖然在對象中被定義,但是this指向的是全局作用域
- 箭頭函數中無法使用
arguments
內置對象來接收實參
// function fn() {
// console.log(arguments);
// }
// fn(1, 2, 3); //Arguments{"0": 1,"1": 2,"2": 3}
const fn = () => {
console.log(arguments);
}
fn(1, 2, 3); //Uncaught ReferenceError: arguments is not defined
- 加括號的函數體返回對象字面量表達式:
var func = route => ({
uname: 'zs', age: 20
})
console.log(typeof func) // function
console.log(func) // route => ({ uname: 'zs', age: 20, id: route.params.id, no: route.params.no })
var objResult = func();
console.log(typeof objResult); // object
console.log(objResult); // {"uname":"zs","age":20}
5. 剩余參數
剩余參數語法允許我們將一個不定數量的參數表示為一個數組,不定參數定義方式,這種方式很方便的去聲明不知道參數情況下的一個函數。
function sum (first, ...args) {
console.log(first); // 10
console.log(args); // [20, 30]
}
sum(10, 20, 30)
剩余參數方便了箭頭函數接收多個實參
const sum = (...args) => {
let total = 0;
args.forEach(item => total += item);
return total;
};
console.log(sum(10, 20));//30
console.log(sum(10, 20, 30));//60
剩余參數和解構配合使用
let students = ['wangwu', 'zhangsan', 'lisi'];
let [s1, ...s2] = students;
console.log(s1); // 'wangwu'
console.log(s2); // ['zhangsan', 'lisi']
6. 對象值省略
在es6中,如果對象的屬性名和值的變量名一樣,那么就可以省略值,直接寫屬性名即可
let User = '老王';
let obj = {
//User: User
User
}
三、ES6 內置對象的擴展
1. Array 的擴展方法
擴展運算符(展開語法)
數組拆分
擴展運算符...
可以將數組轉為用逗號分隔的參數序列,若把參數序列以實參傳入方法中,逗號會被當成多個參數的分隔符。
//
let ary = [1, 2, 3];
//下面一行會報錯(vscode編譯器報錯, 瀏覽器運行報錯):無法識別“...”
...ary // 1, 2, 3
console.log(...ary); // 1 2 3
console.log(1, 2, 3)//1 2 3
擴展運算符不能拆分對象
let obj = {
0: 'gh',
1: 11,
};
console.log(...obj);//Uncaught TypeError: Found non-callable @@iterator
數組合並
擴展運算符應用於數組合並
//方法一
let ary1 = [1, 2, 3];
let ary2 = [3, 4, 5];
let ary3 = [...ary1, ...ary2];
console.log(ary3);//[1,2,3,3,4,5]
//方法二:
let ary1 = [1, 2, 3];
let ary2 = [3, 4, 5];
ary1.push(...ary2);
console.log(ary1);//[1,2,3,3,4,5]
偽數組轉換
利用擴展運算符將偽數組轉換為真正的數組
<div>1</div>
<div>4</div>
<div>3</div>
<div>6</div>
<div>2</div>
<div>5</div>
<script>
var oDivs = document.getElementsByTagName('div');
console.log(oDivs); //ODivs由div元素對象組成的偽數組 HTMLCollection(6)[div,div,div,div,div,div]
var ary = [...oDivs];
ary.push('a');
console.log(ary); //Array(7)[div,div,div,div,div,div,"a"]
</script>
構造函數方法:Array.from()
Array.from()
將偽數組或可遍歷對象轉換為真正的數組
//定義一個集合(偽數組)
var arrayLike = {
"0": "1",
"1": "2",
"length": 2
}
//轉成數組
/*
form()的第二個參數為回調函數,每遍歷一個數組元素,就執行該箭頭函數,item:當前元素值
作用類似於數組的map方法,用來對每個元素進行處理,將處理后的值放入返回的數組
*/
var ary = Array.from(arrayLike, item => item * 2)
console.log(ary)//Array(2)[2.4]
實例方法:find()
find()
用於找出第一個符合條件的數組成員,如果沒有找到返回undefined
let ary = [{
id: 1,
name: '張三'
}, {
id: 2,
name: '李四'
}];
//find()每遍歷一個數組元素,執行一次回調函數,element:被遍歷數組的當前元素
let target = ary.find(element => element.id == 2);//找數組里面符合條件的值並返回,當數組中元素id等於2的查找出來,注意,只會匹配第一個
console.log(target);//{id:2, name:'李四'}
/*
let target = ary.find(element => element.id == 3);
console.log(target);//undefined
*/
實例方法:findIndex()
findIndex()
用於找出並返回第一個符合條件的數組元素的位置,如果沒有找到返回-1,執行過程與find()
類似
let ary = [1, 5, 10, 15];
let index = ary.findIndex(element => element > 9);
console.log(index); // 2
實例方法:includes()
includes()
判斷某個數組是否包含給定的值,返回布爾值。
let ary = ["a", "b", "c"];
let result = ary.includes('a')
console.log(result)//true
result = ary.includes('e')
console.log(result)//false
2. String 的擴展方法
模板字符串
ES6新增的創建字符串的方式,使用反引號定義
let name = `zhangsan`;
模板字符串中可以解析變量
解析格式:${ }
let name = '張三';
let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan
模板字符串中可以換行
let result = {
name: 'zhangsan',
age: 20,
sex: '男'
}
let html = ` <div>
<span>${result.name}</span>
<span>${result.age}</span>
<span>${result.sex}</span>
</div> `;
在模板字符串中可以調用函數
const fn = () => {return 'hello'};
let greet = `我說:‘${fn()}’`;
console.log(greet); // 我說:‘hello’
實例方法:startsWith()
startsWith()
:表示參數字符串是否在原字符串的頭部,返回布爾值endsWith()
:表示參數字符串是否在原字符串的尾部,返回布爾值
let str = 'Hello ECMAScript 2015';
let r1 = str.startsWith('Hello');
console.log(r1);//true
let r2 = str.endsWith('2016');
console.log(r2)//false
實例方法:repeat()
repeat()
repeat方法表示將原字符串重復n次,返回一個新字符串
console.log("y".repeat(5));//'yyyyy'
3. Set
Set 數據結構
ES6 提供了新的數據結構 Set。它類似於數組,但是成員的值都是唯一的,沒有重復的值。
Set數據初始化
Set本身是一個構造函數,用來生成 Set 數據結構
const s = new Set();
//Set.prototype.size : 返回 Set 對象中的值的個數
console.log(s.size);//0
Set函數可以接受一個數組作為參數,用來初始化
const set = new Set([1, 2, 3, 4, 4]);//{1, 2, 3, 4}
console.log(set);//Set(4){1,2,3,4}
console.log(set.size);//4
數組去重
利用Set數據結構的特性,可實現數組中重復元素的除去
注意:擴展運算符...
可結構Set對象
const s3 = new Set(["a", "a", "b", "b"]);
console.log(s3.size);//2
//結構Set對象
const ary = [...s3];
console.log(ary);//Array(2)["a", "b"]
實例方法
方法 | 功能 |
---|---|
add(value) | 添加某個值,返回 Set 結構本身 |
delete(value) | 刪除某個值,返回一個布爾值,表示刪除是否成功 |
has(value) | 返回一個布爾值,表示該值是否為 Set 的成員 |
clear() | 清除所有成員,沒有返回值 |
const s = new Set();
s.add(1).add(2).add(3); // 向 set 結構中添加值 , 可鏈式操作
s.delete(2) // 刪除 set 結構中的2值
s.has(1) // 表示 set 結構中是否有1這個值 返回布爾值
s.clear() // 清除 set 結構中的所有值
//注意:刪除或添加的是元素的值,不是代表的索引
Set對象的遍歷
Set 結構的實例與數組一樣,也擁有forEach
方法,用於對每個成員執行某種操作,沒有返回值。
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value)//a b c
})