共计 3554 个字符,预计需要花费 9 分钟才能阅读完成。
ES6 是个啥
ECMAScript 是国际通过的标准化脚本语言 JavaScript 由 ES,BOM,DOM 组成 ES 是 JavaScript 的语言规范,同时 JavaScript 是 ES 的实现和扩展 6 就是 JavaScript 语言的下一代标准
关于 ES6 的一些知识
1.let、const
ES5 中的作用域有:函数作用域,全局作用域 ES6 新增了块级作用域。由 {} 包括(if 和 for 语句也属于块级作用域)
{
var a = 1;
let b = 2;
}
console.log(a)//1
console.log(b)//undefined
let、const、var 的区别 var:可以跨块级作用域访问,不能跨函数作用域访问 let:只能在块级作用域访问,不能跨函数使用 const:定义常量,必须初始化且不能修改,只能在块级作用域内使用关于变量提升:var 不论声明在何处都会莫默认提升到函数 / 全局最顶部,但是 let 和 const 不会进行变量提升
2.arrow function 箭头函数
箭头函数相当于匿名函数,简化了函数的定义定义就用 => 一个箭头
箭头函数有两种格式:第一种:只包含一个表达式
x=>x++
相当于
function(x)}{
return x++;
}
第二种:包含多条语句:
// 包含判断等
x=>{
if(x>0){
return x++;
}
else{
x–;
}
}
// 多个参数
(x,y,z….)=>x+y+z+…+
// 无参数
()=>1
// 返回对象
x=>({obj:x})// 注意符号, 避免和函数体的 {} 冲突
使用箭头函数时,函数体内的 this 对象,就是定义时所在的对象
3.Promise
定义:Promise 对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作
关于同步 & 异步 JavaScript 是基于事件驱动的单线程运行机制(why:浏览器中至少有三个线程:js 引擎线程,gui 渲染线程,浏览器事件触发线程 js 操作 dom,浏览器事件触发都会影响 gui 渲染效果,因此他们之间存在互斥的关系,使用多线程会带来非常复杂的同步问题(a 线程在某个 DOM 节点添加内容。b 线程删除了该节点)同步:即单线程模式,所有的任务都在主线程上执行,形成一个执行栈 *,如函数调用后需要等待函数执行结束后才能进行下一个任务,如果某个任务执行时间过长(如死循环),容易造成线程阻塞,影响下面任务的正常进行异步:可以一起执行多个任务,函数调用后不会立刻就返回执行结果,异步任务会在当前脚本所有的同步任务执行结束后再执行。异步任务不进入主线程,而是进入任务队列,在某个任务可以执行时,等待主线程读取任务队列,随后该任务将进入主线程执行异步任务的实现,最经典的就是 setTimeout()/setInterval()他们的内部运行机制完全一样,前者指定的代码只执行一次,后者为反复执行
setTimeout(function(){
console.log(“taskA,yibu”);
},0)
console.log(“taskB,tongbu”);
//taskB,tongbu
//taskA,yibu
即使延时事件为 0,但由于它属于异步任务,仍需要等待同步任务执行结束后再执行
综合看,整体的执行顺序为:先执行执行栈中的内容,执行完毕后,读取任务队列,寻找对应的异步任务,结束等待状态,进入执行栈执行,不断循环(Event Loop)只要主线程空了,就会去读取任务队列
关于回调函数,callback()回调函数即是会被主线程挂起的代码异步任务必须指定回调函数,当主线程开始读取任务队列,执行异步任务的时候,执行的就是对应的回调函数
言归正传,继续理解 Promise
promise 的三种状态:
pending:初始状态
fulfilled:操作成功
rejected:操作失败
Promise 可以由 1 ->2/1->3 一旦状态变化,便会一直保持这个状态,不再改变。当状态改变 Promise.then 绑定的函数就会被调用
构建 Promise
var promise = new Promise(function(resolve,reject){
if(/* 操作成功 */)
resolve(data);
else
reject(error);
});
异步操作成功调用 resolve,将结果作为参数传递出去异步操作失败调用 reject,将报出的错误作为参数传递出去
Promise 构建完成后,使用 then 方法指定 resolve 状态和 reject 状态的回调函数 promise.then(成功回调函数,失败的回调函数(非必要))// 这两个函数都接受 promise 传出的值作为参数
promise.then(function(data){do xxxx for success},function(error){do xxxx for failure});
Promise 新建后就执行,then 方法指定的回调函数会在当前脚本的所有同步任务执行结束后再执行
例子:
var promise = new Promise(function(resolve, reject) {
console.log(‘before resolved’);
resolve();
console.log(‘after resolved’);
});
promise.then(function() {
console.log(‘resolved’);
});
console.log(‘outer’);
//before resolved
//after resolved
//outer
//resolved
Promise 的优势在于,可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。能够简化层层回调的写法。Promise 的精髓在于,用维护状态、传递状态的方式使得回调函数能够及时调用,比传递 callback 要简单、灵活
Promise 的其他方法
.catch()
用于指定发生错误时的回调函数,等同于 reject 部分和 reject 的区别:promise.then(onFulfilled,onRejected)在 onFulfilled 发生异常,在 onRejected 中捕获不到 promise.then(onFulfilled).catch(onRejected)能够捕获异常。也可以用 then 替换,只是写法不同。本质上没有区别
.all()
用于将多个 Promise 实例包装成一个新的 Promise 实例
var p = Promise.all([p1, p2, p3]);
p1p2p3 都需为 promise 实例当 p1p2p3 都为 fulfilled 时,p 才会变为 fulfilled 只要有一个变为 rejected,p 就会变成 rejected
.race()
用于将多个 Promise 实例包装成一个新的 Promise 实例与 all()的区别类似于 AND 和 ORp1p2p3 有一个状态发生改变,p 的状态就发生改变,并返回第一个改变状态的 promsie 返回值,传递给 p
.resolve()
看作 new Promise()的快捷方式实例:
Promise.resolve(‘Success’);
/******* 等同于 *******/
new Promise(function (resolve) {
resolve(‘Success’);
});
让对象立刻进入 resolved 状态
4.generate
可以将 generate 理解为一个能够多次返回的“函数”
function* foo(x){
yield x++;
yield x+2;
yield x+3;
return x*x;
}
由 function* 定义,并且 yield 也可以返回数据
调用 generate 的方法:不断的使用 next()
var f = foo(0);
console.log(f.next());// 0 false
console.log(f.next());// 1 false
console.log(f.next());// 3 false
console.log(f.next());// 4 true
使用 for of 结构
for (var x of foo(0)) {
console.log(x); // 依次输出 0 1 3 (没有输出 4 原因不详)
}
每执行一次后就暂停,返回的值就是 yield 的返回值,每次返回一个值,直到 done 为 true,这个 generate 对象已经全部执行完毕 generate 更像一个能够记住执行状态的函数
实际上 generate 不算是一个函数,它的返回值不是变量也不是函数,而是一个可迭代的对象该对象类似一个元素被定义好的数组,保存的是一种规则而不元素本身,不能够随机访问,遍历也只能够遍历一次,因为规则只保存了上次的状态
参考文档 1:讲解 JavaScript 的线程运作
参考文档 2:讲解 Promise
参考文档 3:关于 generate