ES6兼用性
虽然我用的电脑都能兼容es6的语法,凡是有些人的电脑真是老古董,浏览器不知道是多少年的版本了。如果不靠第三方转换es5语法,就硬写es6的语法,可能有些浏览器不兼容。
01. let/const
let
- 不允许重复声明;
- 块儿级作用域(局部变量);
不存在变量提升;
就是在声明变量之前就使用变量,var可以,但let不行
不影响作用域链;
子块里面可以访问父块的let
// let关键字使用示例:
let a; // 单个声明
let b,c,d; // 批量声明
let e = 100; // 单个声明并赋值
let f = 521, g = 'iloveyou', h = []; // 批量声明并赋值
const
- 声明必须赋初始值;
- 标识符一般为大写(习惯);
- 不允许重复声明;
- 值不允许修改;
- 块儿级作用域(局部变量);
- 如果常量是一个数组或者对象,不能修改这个数组或者对象,但是能修改这个数组或者对象内部的值
02. 解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值数组解构
代码说明
const F4 = ["苹果","梨子","香蕉","西瓜"];
let [a,b,c,d]=F4; //这样赋值abcd就和上面的数组里面的数值一一对应
console.log(a);
console.log(b);
console.log(c);
console.log(d);
运行结果
对象解构
代码说明
```javascript const A ={ name:”张三”, age:23, score:[100,98,56,34], method:function(){
} }console.log("A的方法");
let {name,age,score,method} =A;//必须与对象属性名相同 console.log(name); console.log(age); console.log(score); console.log(method);
<a name="JEFVm"></a>
##### 运行结果

<a name="lpnBg"></a>
# 03. 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,在键盘tab键上面<br />特点:
-
字符串中可以出现换行符;
- 可以使用 **${xxx}** 形式引用变量,进行字符串拼接;
<a name="fk58N"></a>
##### 代码说明
```javascript
let html =`
<div>
<p>哈哈哈</p>
</div>`;
字符串拼接
代码说明
let abc="这是一个字符串";
let html2 =`
<div>
<p>${abc}</p>
</div>`;
console.log(html2);
运行结果
04. 简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁;
代码说明
let name ="张三";
let eat =function(){
console.log("吃饭");
};
let score=[20,30,54]
//es6简便的写法
let A ={
name,
eat,
score
}
//等同于这种写法
let B={
name:name,
eat:eat,
score:score
}
console.log(A);
console.log(B);
运行结果
05. 箭头函数
ES6允许使用箭头(=>)定义函数,箭头函数提供了一种更加简洁的函数书写方式,箭头函数多用于匿 名函数的定义;
代码说明
let a =function(){
//这是es5声明匿名函数并且赋值的写方法
};
let b = (q,w)=>{
return q+w;
//es6中的箭头函数,省略了function关键字
//括号里面同样写形参
};
//调用函数,名字加参数
console.log(b(1,2));
注意
- 如果形参只有一个,则小括号可以省略;
- 函数体如果只有一条语句,则花括号可以省略,不用写return,函数的返回值为该条语句的执行结果;
- 箭头函数 this 指向声明时所在作用域下 this 的值;
- 箭头函数不能作为构造函数实例化;
- 不能使用 arguments,用来获取函数的实参;
代码说明
```javascript //箭头函数如果只有一个参数,小括号可以省略 let aa = name =>{ return “这是名字:”+name; } console.log(aa(“张三”));
//箭头函数如果只有一条语句,花括号也可以省略,不用写return,函数的返回值就是这条语句的 执行结果 let bb = name => “这是新名字:”+name; console.log(bb(“李四”));
//箭头函数不能使用arguments let a =function(){ console.log(arguments); }; a();//可以使用
let b =()=> console.log(arguments); b();
<a name="iUj4B"></a>
##### 运行结果

<a name="GnQht"></a>
# 06. 参数赋值初始值
<a name="o8aq7"></a>
##### 代码说明
```javascript
let a = (q,w,e) => console.log(q+w+e);
a(1,2,3);//能正常执行
a(1,2);//少一个参数就是报错
a = (q,w,e=10) => console.log(q+w+e); //一般设有初始值的参数都放在后面
a(1,2);//不填第三个参数就使用默认值10,填了第三个参数就使用填写的参数
运行结果
07. 剩余参数
剩余参数和 arguments对象之间的区别主要有三个:
- 剩余参数…args 只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。
- arguments对象不是一个真正的数组,而剩余参数是真正的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach或pop。
- arguments对象还有一些附加的属性 (如callee属性)
代码说明
```javascript let a= function(){ console.log(arguments); } a(“张三”,”李四”,”赵柳”);
//形参写上 …args ,写在最后一个参数 let b=(…args)=>{ console.log(args); //拿到的是一个数组 } b(“哈哈哈”,”呵呵呵”,”嘿嘿嘿”,”嘻嘻嘻”);
let c=(q,w,…args)=>{ console.log(“q:”+q); console.log(“w:”+w); console.log(“args:”+args); } c(“哈哈哈”,”呵呵呵”,”嘿嘿嘿”,”嘻嘻嘻”)
<a name="pnfXl"></a>
##### 运行结果

<a name="ytYce"></a>
# 08. 扩展运算符[...]
<a name="sCfFu"></a>
##### 代码说明
```javascript
const A=["张三","李四","王五","赵柳"];
const B=["西瓜","苹果","桃子","榴莲"];
//合并数组
const C=[...A,...B];
console.log(C);
//克隆数组,这个不是引用A的内存地址了
const D=[...A];
console.log(D);
//把伪数组转换成数组
let a =new Set([1,2,3,4]);//声明一个set集合
let arr=[...a];//把集合转换成数组
console.log(arr);
运行结果
09. 迭代器
原生具备 iterator 接口的数据(可用 for of 遍历):
- Array;
- Arguments;
- Set;
- Map;
- String;
- TypedArray;
- NodeList;
代码说明
```javascript const A=[“张三”,”李四”,”王五”,”赵柳”];
//for of遍历数组里面的内容 for(let item of A){ console.log(item); }
//for in遍历数组里面的索引 for(let index in A){ console.log(index); }
<a name="M5oca"></a>
##### 运行结果

<a name="Yed6B"></a>
# 10. 生成器
可以这么理解,可以暂停的函数。执行到一部分,突然不想执行了,停一下,过一会又想继续执行那个函数,还可以接着执行。
yield相当于函数的分隔符,把函数分成一段一段的,调用一次执行一段,再调用一次同样的方法,会执行第二段,以此迭代,直到调用完最后一段。<br />3个yield把函数分成4段。
<a name="WG6Q5"></a>
##### 代码实现
```javascript
function * gen() {
//这是第一段
//yield好比结尾符号,我在中间部分不写,写在yield限定符的后面,也属于第一段的范围。
yield console.log("打印的第一段内容");
//这是第二段
console.log("打印的第二段内容");
yield '名字'
//这是第三段
console.log("打印的第三段内容");
yield
//这是第四段
console.log("打印的第四段内容");
}
let iterator = gen();
//每执行一个next方法,就会执行函数中的一段,会迭代执行,直到用next执行完
iterator.next();
//第二次调用next方法,就执行第二段
console.log(iterator.next()); //第二段,只有写字符串,才有value值
console.log(iterator.next());//第三段,yield后面不写,打印出来没有value
iterator.next(); //这是执行第四段
console.log("遍历");
for(let i of gen()){
//执行函数里面的每一段代码,打印全部yield的值,如果yield后面没有写字符串,是没有值的
console.log(i);
}
运行结果
使用案例
这么一个需求,调用方法后,一秒钟后打印111,又过两秒钟后打印222,又过三秒钟后打印333
代码说明
这样解决了回调地狱的问题,一层套一层,套多了,缩进很让人头疼
function one(){
setTimeout(()=>{
console.log(111);
a.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
a.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
},3000)
}
function * gen(){
one();
yield '第一段结尾'
two();
yield '第二段结尾'
three();
}
let a=gen();
a.next();
next传参案例
next方法可以传参数,第二次调用next方法传入的参数会作为第一个yield的返回结果。以此类推。
代码实现
function one(){
setTimeout(()=>{
let data="111111111111";
a.next(data);
},1000)
}
function two(){
setTimeout(()=>{
let data="22222222222";
a.next(data);
},2000)
}
function three(){
setTimeout(()=>{
let data="3333333333333333333";
a.next(data);
},3000)
}
function * gen(){
one();
let a=yield
console.log(a);
two();
let b= yield
console.log(b);
three();
let c=yield
console.log(c);
}
let a=gen();
a.next();
运行结果
11.Promse
语法上 Promise 是一个构造函数,用来封装异步操作 并可以获取其成功或失败的结果;
代码说明
//实例化Promise对象
//Promise的参数是一个函数,而且这个函数有两个形参,连个参数名字随便写
const p = new Promise((resolve,reject)=>{
setTimeout(() => {
let data="经过了5秒成功了";
let data2="经过5秒失败了";
//完成了一些列操作过后,可以调用Promise的两个参数函数,来改变p的状态
//p有3个状态,初始化,成功,失败
//调用第一个参数函数,p对象的状态就会变为成功
resolve(data);
//调用第二个参数函数,p对象的状态就会变成失败
reject(data2);
//两个都写只有第一个生效
}, 5000);
})
//调用promise对象的then方法
//then方法接受两个参数,两个函数,而且每个函数都有一个形参
//p的状态为成功,就会回调一个函数,p的状态为失败,就会回调第二个函数
p.then((value)=>{
console.log(value);
},(error)=>{
console.error(error);
})
执行异步事件
传输数据,打开文件,写入文件等都需要一定的事件,如果一个事情就要花费3-5秒,几件事同步执行就要花几十秒。异步就是让他们一起执行,最短的一件事需要3秒,最长的一件事需要7秒,那么所有事件完成的时间就是7秒。
代码说明
//定义了三个异步事件,都需要一定事件完成,让他们同时执行,节约时间
const p = new Promise((resolve,reject)=>{
setTimeout(() => {
let data="经过了5秒成功了";
resolve(data);
}, 5000);
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(() => {
let data="经过了3秒失败了";
reject(data);
}, 3000);
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(() => {
let data="经过了6秒成功了";
resolve(data);
}, 6000);
})
p.then((value)=>{
console.log(value);
},(error)=>{
console.error(error);
});
p2.then((value)=>{
console.log(value);
},(error)=>{
console.error(error);
});
p3.then((value)=>{
console.log(value);
},(error)=>{
console.error(error);
})
运行结果
then的返回结果
then方法的返回结果也是一个Promise对象,但是这个对象的状态由then方法执行结果决定。
p.then(),如果p的状态的成功的,then方法返回的promise对象状态就是成功,反之就是失败。但是这样没有返回的值。
then方法里面也可以写return new Promise,这个新的promise对象的状态决定then方法的返回状态。
这样就可以进行链式编程p.then().then().then()
,这么写可读性差。
12. set集合
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
代码说明
//声明set
let s=new Set();
console.log(s,typeof s);
//可以传入一个可迭代输入
let a=['香蕉','西瓜','苹果','西瓜'];
let ss=new Set(a);//会自动去重
console.log(ss,typeof ss);
//元素的个数
console.log(ss.size);
//添加新元素
ss.add('哈密瓜');
console.log(ss,typeof ss);
//删除元素
ss.delete('哈密瓜');
//检查集合里面有没有这个元素
console.log(ss.has("香蕉"));
//清空集合
ss.clear();
console.log(ss);
运行结果
13. Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类
型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和
『for…of…』进行遍历;
Map就像升级的对象,字典一样
//声明map
let a=new Map();
//添加元素
a.set('name','张三');
a.set('m',()=>console.log('哈哈哈'));
//获取元素个数
console.log(a.size);
//获取
console.log(a.get('m'));
//清空
a.clear();
14. Class
class Phone{
// 构造方法,名字是固定的
constructor(brand,price) {
this.brand = brand;
this.price = price;
}
// 打电话,方法必须使用该方式写
call(){
console.log("我可以打电话!");
}
}
let HuaWei = new Phone("华为",5999);
HuaWei.call();
console.log(HuaWei);