一、變量聲明
1、let
a、let不允許重複聲明同一個變量
var a = 0;
let a = 2; // 報錯;Identifier 'a' has already been declared
function demo (num) {
let num; //這裏使用let聲明,同樣屬於重複聲明變量
}
{
var b = 0;
}
let b = 2;
b、let沒有變量提升
console.log(c); // c is not defined
let c = 0;
typeof wuzhe // 這裏也會報錯
let wuzhe;
c、暫時性死區
var foo = 100;
// ES6明確規定,如果代碼塊出現let、const聲明,那麼一旦形成了
// 封閉作用域,在聲明之前使用就會報錯
if (true) {
foo = "abc";
console.log(foo); // 報錯; foo is not defined
// 在let聲明變量"foo"之前,都屬於變量"foo"的死區
let foo;
}
d、塊級作用域
{
// 在塊級作用域以內聲明的let變量,只能在這裏面訪問的到
let a = 10;
console.log(a);
}
// console.log(a); // 報錯
for循環裏的塊級作用域:
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // 報錯
var arr=[];
for (let i = 0; i < 10; i++){
// 在es6中每次運行,這裏都會形成一個塊級作用域
arr[i] = function(){
console.log(i);
}
}
for(let val of arr){
val(); // 會循環輸出0到9的所有數字
}
塊級作用域可以嵌套:
{
let p = 1;
{
var o = 0;
console.log(o);
console.log(p);
}
}
這裏的{ }裏面的代碼會立即執行,相當於es5裏面的立即執行函數IIFE;2、const
let裏面的規則,也適用於const;但const更加嚴格;
a、const聲明變量的同時必須立即賦值
const a = 1; //正確
const b;
b = 1; //報錯;Missing initializer in const declaration
b、const聲明的是常量,引用地址無法被改變
const hello = 'hello';
hello = 'world'; // 報錯;Assignment to constant variable
對於對象和數組類的引用地址,可以改變其屬性或值:
const arr = [];
arr.push('DNEDU');
arr.push('THINK');
console.log(arr); // ["DNEDU", "THINK"]
const objs = {};
objs.name = 'jack';
objs.name = 'tom';
console.log(objs.name); // 'tom'
objs = {}; // 報錯;Assignment to constant variable
二、解構賦值
1、聲明多個變量
let [a, b, c] = [3, 2, 1];
console.log(a, b, c); // 3 2 1
2、賦值部分變量
let [, , d] = [4, 5, 6]
console.log(d); // 6
let [, , [e, f]] = [, , [6, 7]];
console.log(e, f); // 6 7
3、使用...匹配剩餘參數
let [head, ...tail] = [8, 9, 10, 11, 12, 13];
console.log(head, tail); // 8 [9, 10, 11, 12, 13]
4、對象的解構賦值
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
如果變量名與屬性名不一致,必須寫成下面這樣。let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
實際上最後的值是賦值給了 :後面的那個實際變量;三、函數
1、給函數設置默認參數
function test ( a = 1, b =2) {
a = 6
console.log(a, b);// 6 2
}
test();
利用結構賦值給函數傳參:
function test03 ({a = 1, b = 2}) {
console.log(a, b); // 5 6
}
test03({ a : 5, b : 6});
2、箭頭函數
// 第一個:函數名,第二個參數,第三個方法體
let test05 = a => a;
console.log(test05(666)); //輸出 666
箭頭函數省略了function關鍵字;當只有一個參數時可以省略括號,當沒有參數或有多個參數時,必須加上括號;如果函數體只有一個return 語句,則可以簡寫省略return關鍵字,直接寫返回的內容;
箭頭函數有幾個使用注意點:
- 函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
- 不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
- 不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。
- 不可以使用yield命令,因此箭頭函數不能用作 Generator 函數。
關於this的測試:
let obj = {
fn: () => {
console.log(this); // window
}
};
obj.fn();
function Demo() {
this.a = "hello";
setTimeout(() => {
console.log(this); // 指向的是 dn,也就是Demo的實例
});
}
let dn = new Demo();
四、Promise
1、Promise、then、all
Promise的基本使用方法:
function one () {
return new Promise(function(resolve, reject){
setTimeout(()=>{
console.log('煮水');
resolve();
}, 3000);
});
}
function two () {
return new Promise(function(resolve, reject){
setTimeout(()=>{
console.log('洗杯子');
resolve();
}, 2000);
});
}
function three () {
return new Promise(function(resolve, reject){
setTimeout(()=>{
console.log('泡茶葉');
resolve();
}, 1000);
});
}
console.time('promise');
one().
then(function () {
return two();
}).
then(function () {
return three();
}).
then(function(){
console.timeEnd('promise');
});
執行結果如下:
我們再使用Promise.all測試下:
console.time('promiseAll');
Promise.all([one(), two(), three()]).then(function(){
console.timeEnd('promiseAll');
},function(error){
console.log(error)
});
我們發現then()方法可以按順序執行任務,all()方法是異步執行任務的,當三個任務都完成了之後,再執行最後的.then()裏面的回調;
我們再來看一個更復雜的例子:
const flag = false;
let p1 = new Promise((resolve, reject) => {
console.log('開始異步');
throw 'ee';
setTimeout(() => {
flag ? resolve('成功') : reject('失敗');
}, 1000);
});
p1.then(
result => {
console.log('success1: ', result);
// throw '報錯啦';
return '成功回調函數的結果';
},
result => {
console.log('fail1: ', result);
return '失敗回調函數的結果';
}
)
.catch(reason => {
console.log('error1:', reason);
return '異常處理結果';
})
.then(
result => {
console.log('success2: ', result);
},
result => {
console.log('fail2: ', result);
}
)
.catch(reason => {
console.log('error2:', reason);
});
執行結果:
從上面代碼和執行結果可以瞭解到promise大概的執行流程:
- 先執行構造函數內的同步代碼
- 支持鏈式調用,而且then和catch返回的是全新的promise對象
- catch只會在異步操作失敗或者異常,並且前面流程未定義reject回調函數的時候觸發
2、async和await黃金搭檔
async和await基本的規則:
- async標識這是一個異步函數,await只能應用在這個async函數裏面
- await表示在這裏,會等待Promise返回結果之後再繼續執行
- await後面跟着的應該是一個Promise對象,但是如果返回其他值,但是就不會出現異步的效果了
- await只能再async上下文裏面纔有效
基本的用法:
var sleep = function ( time ) {
return new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('休眠結束…………');
resolve();
}, time);
});
}
// async: 給方法一個標識,告訴他這是一個需要異步的函數
var start = async function () {
// await處理異常的方法
try {
console.log('開始休眠……');
await sleep(3000);
console.log('甦醒了……');
} catch(err) {
console.log(err);
}
}
start();
await必須在async上下文中:
var arr = [1,2,3];
var fn = async function () {
// 這裏用forEach就會報錯await無效
/*arr.forEach(v => {
await sleep(2000);
});*/
for (let v of arr) {
console.log(v);
await sleep(2000);
}
};
fn();
以上就是對es6的基本瞭解,如有錯誤,歡迎指正,以後學到更多有用的es6技術再慢慢添加,謝謝!