一、let 和 const 定義的變量不會出現變量提高,而 var 定義的變量會提高。ajax
二、let 和 const 是JS中的塊級做用域json
三、let 和 const 不容許重複聲明(會拋出錯誤)數組
四、let 和 const 定義的變量在定義語句以前,若是使用會拋出錯誤(造成了暫時性死區),而 var 不會。promise
五、const 聲明一個只讀的常量。一旦聲明,常量的值就不能改變(若是聲明是一個對象,那麼不能改變的是對象的引用地址) 變量提高就是變量在聲明以前就可使用,值爲undefined。 在代碼塊內,使用 let/const 命令聲明變量以前,該變量都是不可用的(會拋出錯誤)。這在語法上,稱爲「暫時性死區」。暫時性死區也意味着 typeof 再也不是一個百分百安全的操做。 暫時性死區的本質就是,只要一進入當前做用域,所要使用的變量就已經存在了,可是不可獲取,只有等到聲明變量的那一行代碼出現,才能夠獲取和使用該變量。安全
箭頭函數沒有本身的 this, 它的this繼承於上一層代碼塊的this。 箭頭函數是普通函數的簡寫,能夠更優雅的定義一個函數,和普通函數相比,有如下幾點差別: 一、函數體內的 this 對象,就是定義時所在的對象,而不是使用時所在的對象。 二、不可使用 arguments 對象,該對象在函數體內不存在。若是要用,能夠用 rest 參數代替。 三、不可使用 yield 命令,所以箭頭函數不能用做 Generator 函數。 四、不可使用 new 命令,由於:沒有本身的 this,沒法調用 call,apply。bash
Generators(生成器)
生成器是一個函數,它能夠退出函數,稍後從新進入函數。
// generator-example.js
function* generator(){
yield 1;
yield 2;
yield 3;
};
for (const g of generator()) {
console.log(g);
}
// Output:
// 1
// 2
// 3複製代碼
promise構造函數是同步執行的,then方法是異步執行的
數據結構
all(list) {
return new Promise((resolve, reject) => {
let resValues = [];
let counts = 0;
for (let [i, p] of list) {
resolve(p).then(res => {
counts++;
resValues[i] = res;
if (counts === list.length) {
resolve(resValues)
}
}, err => {
reject(err)
})
}
})
}
Promise._race = promises => new Promise((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, reject)
})
})
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};複製代碼
一、setTimeoutapp
console.log('script start') //1. 打印 script start
setTimeout(function(){
console.log('settimeout') // 4. 打印 settimeout
}) // 2. 調用 setTimeout 函數,並定義其完成後執行的回調函數
console.log('script end') //3. 打印 script start
// 輸出順序:script start->script end->settimeout複製代碼
二、Promise 異步
Promise自己是同步的當即執行函數, 當在executor中執行resolve或者reject的時候, 此時是異步操做, 會先執行then/catch等,當主棧完成後,纔會去調用resolve/reject中存放的方法執行,打印p的時候,是打印的返回結果,一個Promise實例。async
console.log('script start')
let promise1 = new Promise(function (resolve) {
console.log('promise1')
resolve()
console.log('promise1 end')
}).then(function () {
console.log('promise2')
})
setTimeout(function(){
console.log('settimeout')
})
console.log('script end')
// 輸出順序: script start->promise1->promise1 end->script end->promise2->settimeout複製代碼
三、async/await
async function async1(){
console.log('async1 start');
await async2();
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start');
async1();
console.log('script end')
// 輸出順序:script start->async1 start->async2->script end->async1 end
複製代碼
async 函數返回一個 Promise 對象,當函數執行的時候,一旦遇到 await 就會先返回,等到觸發的異步操做完成,再執行函數體內後面的語句。能夠理解爲,是讓出了線程,跳出了 async 函數體。
var target = {
name: 'obj'
};
var logHandler = {
get: function(target, key) {
console.log(`${key} 被讀取`);
return target[key];
},
set: function(target, key, value) {
console.log(`${key} 被設置爲 ${value}`);
target[key] = value;
}
}
var targetWithLog = new Proxy(target, logHandler);
targetWithLog.name; // 控制檯輸出:name 被讀取
targetWithLog.name = 'others'; // 控制檯輸出:name 被設置爲 others
console.log(target.name); // 控制檯輸出: others複製代碼
Set 和 Map 主要的應用場景在於 數據重組 和 數據儲存 Set 是一種叫作集合的數據結構,Map 是一種叫作字典的數據結構
一、集合(Set) ES6 新增的一種新的數據結構,相似於數組,但成員是惟一且無序的,沒有重複的值。 Set 自己是一種構造函數,用來生成 Set 數據結構。
二、字典(Map) 集合 與 字典 的區別:
共同點:集合、字典 能夠儲存不重複的值
不一樣點:集合 是以 [value, value]的形式儲存元素,字典 是以 [key, value] 的形式儲存
一、回調函數(callback) setTimeout(() => { // callback 函數體 }, 1000) 缺點:回調地獄,不能用 try catch 捕獲錯誤,不能 return;
回調地獄的根本問題在於:
缺少順序性: 回調地獄致使的調試困難,和大腦的思惟方式不符 嵌套函數存在耦合性,一旦有所改動,就會牽一髮而動全身,即(控制反轉) 嵌套函數過多的多話,很難處理錯誤;
ajax('XXX1', () => {
// callback 函數體
ajax('XXX2', () => {
// callback 函數體
ajax('XXX3', () => {
// callback 函數體
})
})
})複製代碼
優勢:解決了同步的問題(只要有一個任務耗時很長,後面的任務都必須排隊等着,會拖延整個程序的執行。)
二、Promise
Promise就是爲了解決callback的問題而產生的。
Promise 實現了鏈式調用,也就是說每次 then 後返回的都是一個全新 Promise,若是咱們在 then 中 return ,return 的結果會被 Promise.resolve() 包裝
優勢:解決了回調地獄的問題
ajax('XXX1')
.then(res => {
// 操做邏輯
return ajax('XXX2')
}).then(res => {
// 操做邏輯
return ajax('XXX3')
}).then(res => {
// 操做邏輯
})複製代碼
缺點:沒法取消 Promise ,錯誤須要經過回調函數來捕獲
三、Generator 特色:能夠控制函數的執行,能夠配合 co 函數庫使用
function *fetch() {
yield ajax('XXX1', () => {})
yield ajax('XXX2', () => {})
yield ajax('XXX3', () => {})
}
let it = fetch()
let result1 = it.next()
let result2 = it.next()
let result3 = it.next()複製代碼
四、Async/await async、await 是異步的終極解決方案
優勢是:代碼清晰,不用像 Promise 寫一大堆 then 鏈,處理了回調地獄的問題
缺點:await 將異步代碼改形成同步代碼,若是多個異步操做沒有依賴性而使用 await 會致使性能上的下降。
async function test() {
// 如下代碼沒有依賴性的話,徹底可使用 Promise.all 的方式
// 若是有依賴性的話,其實就是解決回調地獄的例子了
await fetch('XXX1')
await fetch('XXX2')
await fetch('XXX3')
}複製代碼
//Promise
const sleep = time => {
return new Promise(resolve => setTimeout(resolve,time))
}
sleep(1000).then(()=>{
console.log(1)
})
//Generator
function* sleepGenerator(time) {
yield new Promise(function(resolve,reject){
setTimeout(resolve,time);
})
}
sleepGenerator(1000).next().value.then(()=>{console.log(1)})
//async
function sleep(time) {
return new Promise(resolve => setTimeout(resolve,time))
}
async function output() {
let out = await sleep(1000);
console.log(1);
return out;
}
output();
//ES5
function sleep(callback,time) {
if(typeof callback === 'function')
setTimeout(callback,time)
}
function output(){
console.log(1);
}
sleep(output,1000);複製代碼
var getJSON = url=>{
var promise = new Promise((resolve,reject)=>{
var client = new XMLHttpRequest()
client.open("GET",url);
client.onreadystatechange = hander;
client.responseType = "json"
client.setRequesHeader("Accept","application/json");
client.send()
function handler(){
if(this.readyState!==4){
return ;
}
if(this.status===200){
resolve(this.response)
}else {
reject(new Error(this.statusText))
}
}
})
return promise;
}
getJSON("/posts.json").then((json)=>{
console.log(json)
},(error)=>{
console.log(error)
})複製代碼
let promise = new Promise(function(resolve, reject){
resolve('第一次成功')
})
promise.then(function(val) {
// 兩種方法意思都表明報錯,【中斷下一步,直接報錯】
//第一種方法
throw new error()
// 第二種方法
return Promise.reject()
}).then(function(val) {
console.log('被跳過的方法')
}).catch(function(val) {
console.log('返回失敗')
})複製代碼