es6给我们带来了很多新特性
例如:let const promise 箭头函数 解构 class set map proxy 数组
对象新方法 模板字符串
1.变量
ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。
2.let和const
let
块级作用域
只作用于当前代码块
且在同一作用域中不能重复声明变量
但是可以重新赋值
const
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
但如果const指向一个地址,那么地址内的值可以修改,但不可以修改const指向的地址
比如用const声明一个数组
const arr = [1,2,3];
arr[0] = 0;
console.log(arr);
//输出[0,2,3]
当不想const定义的对象被修改时,可以使用Object.freeze()方法
const arr = [1,2,3];
Object.freeze(arr);
arr[0] = 0;
console.log(arr);
//输出[1,2,3]
for循环有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
不存在变量提升
JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。
JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
块级作用域
ES6 允许块级作用域的任意嵌套。
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
3.解构
下面是一个解构的例子,可以初步认识解构
let {a,b} = {a:1,b:2};
console.log(a);
4.Set
Set()方法用于数组去重,输出结果为类数组
let arr = [1,2,3,2];
console.log(new Set(arr));
如果我们想得到一个数组可以这样做,使用es6新增的扩展运算符
let arr = [1,2,3,2];
let arr2 = new Set(arr);
let arr3 = [...arr2]
5.class
基本使用方法
在constructor中传入属性,多个属性需要用逗号隔开
class Person{
constructor(name){
this.name = name
}
say(){
console.log(this.name + "is"+ "...")
}
}
var person1 = new Person('zs');
person1.say()
属性的继承,在constructor里使用super()
class Coder extends Person{
constructor(name,age){
super(name);
this.age = age;
}
}
var coder1 = new Coder('ls',20);
console.log(coder)
如果添加static,则为静态的方法,静态方法不能被子类继承
class Person{
constructor(name){
this.name = name
}
static say(){
console.log(this.name + "is"+ "...")
}
}
var person1 = new Person('zs');
person1.say()
6.promise
promise可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
以下是promise的特点
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
一言蔽之就是避免了“回调地狱”
基本写法
new Promise(function (resolve, reject) {
setTimeout(function(){
if(res.code == 1){
resolve()
}else{
reject()
}
},1000);
}).then((res) => {
console.log('yes')// 成功
}).catch((err)=>{
console.log('no') // 失败
})
Promise规范如下:
●一个promise可能有三种状态: 等待(pending) 、已完成(resolved )、已拒绝(rejected)
●一个promise的状态只可能从 “等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
●promise必须实现then方法 (可以说,then就是promise的核心) ,而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
●then方法接受两个参数, 第一个参数是成功时的回调,在promise由 “等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then"的对象或方法,即thenable对象。
●解决函数的回调嵌套问题
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promi se对象提供统- -的接口, 使得控制异步操作更加容易,Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部扶出的错误,不会反应到外部。第三,当处于Pendi ng状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
promise的方法
all(),当所有promise都成功的时候才会触发all()里面的then,有一个没有成功就会立即触发catch
let p1 = new Promise(function(resolve,reject){
setTimeout(function(){
console.log(1)
resolve();
},300)
})
let p2 = new Promise(function(resolve,reject){
setTimeout(function(){
console.log(2)
resolve();
},600)
})
let p3 = new Promise(function(resolve,reject){
setTimeout(function(){
console.log(3)
resolve();
},900)
})
promise.all([p1,p2,p3]).then(function(){
console.log('over--')
})
race(),最快的成功了就会触发
最后:关于js执行顺序可以参照这一次,彻底弄懂 JavaScript 执行机制