一、为什么学ES6
- 弥补ES5的先天性不足:
比如变量提升、内置对象的方法不灵活、模块化实现不完善等等。
- 为了后面vue、尤其是react框架做好了准备
- 目前大部分公司的项目都在使用es6
二、ES6新特性
- let 和const 命令
- es6的模版字符串
- 增强的函数
- 扩展的字符串、对象、数组功能
- 解构赋值
- Symbol
- Map和Set
- 迭代器和生成器
- Promise对象
- Proxy对象
- async的用法
- 类class
- 模块化实现
三、变量let和const
1、var的问题
可以重复声明
无法限制修改
没有块级作用域
2、let
没有变量提升,不能重复声明,声明变量-可以修改,有块级作用域
3、const
没有变量提升,不能重复声明,声明常量-不能修改,有块级作用域
4、建议
默认情况下使用const,当明确知道声明的变量被修改时使用let
四、模板字符串
使用tab键上的反引号,插入变量时使用${变量名}
const oBox=document.querySelector('.box');
let id=1,
name="缘木鱼";
let htmlStr=`<ul>
<li>
<p id=${id}> ${name}</p>
</li>
</ul>`;
oBox.innerHTML=htmlStr;
// oBox.innnerHTML="<ul><li><p id"+id+">" +name+"</p></li></ul>"
<div class="box">
<ul>
<li>
<p id="1"> 缘木鱼</p>
</li>
</ul>
</div>
五、函数
1、带参数默认值的函数
function add(a,b=20){
return a+b;
}
console.log(add(30));//50
2、默认的表达式也可以是一个函数
function add(a,b=getVal(5)){
return a+b;
}
function getVal(val){
return val+5
}
console.log(add(10));//20
3、剩余的参数
function pick(obj,...keys){
let result=Object.create(null);
for(let i=0;i<keys.length;i++){
result[keys[i]]=obj[keys[i]];
}
return result;
}
function show(a,b,...args){ }
作用:展开数组。展开后的效果,跟直接把数组的内容写在这儿一样
4、箭头函数
使用=>来定义,function=()=>{}
组成:()=》{ }
如果只有一个参数,()可以省
如果只有一个return,{ }可以省
没有this指向,箭头函数内部this值只能通过查找作用域链,一旦使用箭头函数,当前就不存在作用域
使用箭头函数的注意事项:
1、使用箭头函数,函数内部没有arguments
2、箭头函数不能使用new关键字来实例化对象
3、function函数也是一个对象,但是箭头函数不是一个对象,它其实就是一个语法糖
六、解构赋值
解构赋值:是对赋值运算符的一种扩展,针对数组和对象来进行操作
优 点:代码书写上简洁易读
左右两边结构必须一样
声明和赋值不能分开(必须在一句话里完成)
// *****************
let node={
type:'xingming',
name:'muyu'
}
// 完全解构
let {type,name}=node;
console.log(type,name);
let obj={
a:{
name:'木鱼'
},
b:[],
c:'hello,world'
}
// 不完全解构
// let {a}=obj;
// console.log(a);
// 剩余运算符
// let {a,...res}=obj;
// console.log(res);
// 默认值
// let {a,b=30}={a:20};
// 对数组解构
// let arr=[1,2,3];
// let[a,b,c]=arr;
// 可嵌套
// let [a,[b],c]=[1,[2],3];
七、扩展的对象的功能
// es6直接写入变量和函数,作为对象的属性和方法
const name='木鱼',
age=20;
const person={
name,//等价于name:name
age,
sayName(){
console.log(this.name);
}
}
对象的方法:
is( )
比如:判定两个值是否严格相等
console.log(NaN===NaN);//false
console.log(Object.is(NaN,NaN));//true
assign( )
主要用于浅拷贝
作用:对象的合并,Object.assign(target,obj1,obj2,...)
let newObj=Object.assign({},{a:1},{b:2});
console.log(newObj);//{a:1,b:2}
八、Symbol
原始数据类型Symbol,它表示是独一无二的值
const name=Symbol('name');
const name2=Symbol('name');
console.log(name===name2);//false
最大的用途:用来定义对象的私有变量
let s1=Symbol('s1');
console.log(s1);
let obj={
[s1]:'木鱼'
};
// 如果用Symbol定义的对象中的变量,取值时一定要用[变量名]
console.log(obj[s1]);
for(let key in obj){
console.log(key);
}
console.log(Object.keys(obj));
// 获取Symbol声明的属性
// let s=Object.getOwnPropertySymbols(obj);
// console.log(s[0]);
let m=Reflect.ownKeys(obj);
console.log(m);
九、Set和Map
集合:表示无重复值的有序列表
let set=new Set();
console.log(set);
let set=new Set();
console.log(set);
// 添加元素
set.add(2);
set.add('4');
set.add([1,2,3]);
// 删除元素
add.delete(2);
// 校验某个值是否在set中
console.log(set.has('4'));
// 集合的长度
console.log(set.size);
// 将集合转换成数组
let set2=new Set([1,2,3,3,5]);
let arr=[...set2];
console.log(arr);
// // 问题:set中对象的引用无法被释放
// let set3=new Set(),obj={};
// set3.add(obj);
// // 释放当前的资源
// obj=null;
// console.log(set3);
// *****解决方式********
let set4=new WeakSet(),obj={};
set4.add(obj);
// 释放当前的资源
obj=null;
console.log(set4);
WeakSet
不能传入非对象类型的参数
不可迭代
没有forEach()
没有size属性
Map类型是键值对的有序列表,键和值是任意类型
let map=new Map();
// 添加元素
map.set('name','木鱼');
map.set('age',20);
console.log(map.get('name'));
console.log(map);
// 校验元素
map.has('name');//true
// 删除元素
map.delete('name');
// 清除元素
map.clear();
十、数组的扩展功能
// 数组的方法 from() of()
//(1) from() 将伪数组转为真正的数组
function add(){
console.log(arguments);
}
add(1,2,3);
let arr=Array.from(arguments);
console.log(arr);
//扩展运算符,将伪数组转换成真正的数组
console.log([...arguments]);
// from() 还可以接受第二个参数,用来对每个元素进行处理
Array.from(arguments,ele=>ele.textContent);
//(2) of() 将任意的数据类型,转换成数组
console.log(Array.of(3,11,20,[1,2,3],{id:1}));
// (3) copyWith()数组内部将指定位置的元素
// 复制到其他的位置,返回当前数组
// 从3位置往后的所有数值,替换从0位置往后的三个数值
console.log([1,2,3,8,9,10].copyWithin(0,3));//[8,9,10,8,9,10]
// (4) find() findIndex()
// find()找出第一个符合条件的数组成员
let num=[1,2,-10,-20,9,2].find(n => n<0)
// findIndex()找出第一个符合条件的数组成员的索引
let numIndex=[1,2,-10,-20,9,2].findIndex(n => n<0)
// (5)entries() keys() values() 返回一个遍历器 可以使用for...of循环进行遍历
// keys() 对键名的遍历
// values()对值遍历
// entries()对键值对遍历
// console.log(['a','b'].keys());
// 取键
for(let index of ['a','b'].keys()){
console.log(index);
}
// 0,1
// 取值
for(let ele of ['a','b'].values()){
console.log(ele);
}
// a,b
for(let [index,ele] of ['a','b'].entries()){
console.log(index,ele);
}
// 0 'a'
// 1 'b'
// (6)includes()返回一个布尔值,表示某个数组是否包含给定的值
console.log([1,2,3].includes(2));
十一、迭代器
// Iterator
// 是一种新的遍历机制,两个核心
// 1、迭代器是一个接口,能快捷的访问数据,
// 通过Symbol.iterator来创建迭代器 ,通过迭代器的next()获取迭代后的结果。
// 2、迭代器是用于遍历数据结构的指针(数据库的游标)
// 使用迭代
const items=['one','two','three'];
// 创建新的迭代器
const ite=items[Symbol.iterator]();
console.log(ite.next());
//{value:'one',done:false} done为false表示遍历继续,为true表示遍历完成
十二、生成器
// generator函数,可以通过yield关键字,将函数挂起,
为了改变执行流提供了可能,也为异步编程提供了方案
// 它与普通函数的区别:
// 1、function后面 函数名之前有个*
// 2、只能在函数内部使用yield表达式,让函数挂起
// function* func(){
// yield 2;
// }
// 返回一个遍历器对象 可以调用next()
// let fn=func();
// console.log(fn.next());
// 总结:generator函数是分段执行的,yield语句是暂停执行,而next()恢复执行
function* add(){
console.log('start');
let x=yield '2';
console.log('one:'+x);
let y=yield '3';
console.log('two:'+y);
return x+y;
}
const fn=add();
console.log(fn.next());//{value:'2',done:false}
console.log(fn.next(20));//{value:'3',done:false}
console.log(fn.next(30));//{value:50,done:true}
// 使用场景1:为不具备Interator接口的对象提供了遍历操作
function* objectEntries(obj){
// 获取对象的所有的key保存到数组[name,age]
const propKeys= Object.keys(obj);
// 对数组进行遍历
for(const propkey of propKeys){
yield [propkey,obj[propkey]]
}
}
const obj={
name:'木鱼',
age:18
}
obj[Symbol.iterator]=objectEntries;//生成器
console.log(obj);
for(let [key,value] of objectEntries(obj)){
console.log(`${key}:${value}`);
}
// 使用场景2:为异步编程提供了方案