一、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('返回失败')
})复制代码