1.Symbol
说明:ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如你使用了一个他人提供的方法,但又想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突,如果有一种机制,保证每个属性的名字都是独一无二的,这样就从根本上防止属性名的冲突,这就是ES6引入Symbol的原因, 主要被用于定义常量消除魔法字符串: const EVENT_ID = Symbol();
let a = Symbol();
let b = Symbol();
console.log(a==b); // false
let c = Symbol('a');
let d = Symbol('a');
console.log(c==d); // false
console.log(c.toString()); // Symbol(a)
console.log(c.toString()==d.toString()); // true
// 这样写永远拿不到obj中的[a]和[b]
let [e,f] = [Symbol(),Symbol()];
let obj = {
[e]:10,
[f]:20,
g:Symbol()
}
console.log(obj); // {g: Symbol(), Symbol(): 10, Symbol(): 20}
/* 消除魔法字符串
魔法字符串:
指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或数值。风格良好的代码,应该尽量消除魔法字符串,而由含义清晰的变量代替。
*/
let type = {
MERGED:'1',
SPLIT:'2'
}
let card = '1';
switch(card){
case type.MERGED:
console.log('type.MERGED');
break;
case type.SPLIT:
console.log('type.SPLIT');
break;
}
2.解构赋值
其实就是分解结构给多个变量赋值
// 数组解构赋值
let [card1,card2,card3] = [3,4,5];
console.log(card1,card2,card3); // 3 4 5
// 如果赋值就选择赋予的值,没赋值就等于默认值,如果没有默认值就是undefined
let [x,y] = [5];
console.log(x,y); // 5 undefined
let [x1,y1=0] = [5];
console.log(x1,y1); // 5,0
let [x2,y2=0] = [5,10]
console.log(x2,y2); // 5,10
// 函数参数解构
function fn([a,b]){
console.log(a+b); // 5
}
fn([1,4]);
function fn2([a,b=2]){
console.log(a+b); // 7
}
fn2([5]);
// 对象解构赋值:名称必须统一
let {sum,num} = {num:10,sum:20}
console.log(sum,num); // 20,10
let {sum1,a1,b1} = {
a1:2,
b1:4,
sum1: ()=>{
return this.a1+this.b1 // 解构的前提就是每个元素没有交叉联系
}
}
console.log(sum1(),a1,b1); // NaN,2,4
let {p:[a3,{b3}]} = {
p:[
'hello',
{b3:'world'}
]
}
console.log(a3,b3); // hello world
let {length:arrLen} = [12,23,12];
console.log(arrLen) // 3
// 字符串解构
let [i1,i2,i3,i4] = 'abcd';
console.log(i1,i2,i3,i4); // a,b,c,d
let {length:len} = 'abcde';
console.log(len); // 5
let [{length:len1},{length:len2}] = ['abcde','abd']
console.log(len1,len2); // 5,3
/*
使用场景
1.交换变量
2.从函数中国返回多个值
*/
let s1 = 10,s2 = 20;
[s1,s2] = [s2,s1]
console.log(s1,s2) // 20,10
function fnn(){
let ax=10,bx=20,cx=30;
// return [ax,bx,cx]; // 如果数组解构返回,外面的变量名可以和里面的不同,但是顺序相同
return {ax:ax,bx:bx,cx:cx}; // 如果对象解构返回,外面的变量名必须和里面的变量名保持一致
}
// let [s3,s4,s5] = fnn();
// console.log(s3,s4,s5) // 10 20 30
let {ax,bx,cx} = fnn();
console.log(ax,bx,cx) //10 20 30
3.set和map
set:是一个类数组,主要特点是元素不重复
let set1 = new Set([1,2,3,4]);
console.log(set1); // Set(4) {1, 2, 3, 4}
let set2 = new Set([1,2,3,1,4,2]);
console.log(set2); //Set(4) {1, 2, 3, 4}
//数组去重
let arr = Array.from(new Set([1,2,3,2,1,3])); // 将类数组转化为数组
console.log(arr); // [1,2,3]
// Set增加元素和删除元素
let likeArr = new Set();
likeArr.add(10);
likeArr.add(20);
likeArr.add(30);
likeArr.add(10);
console.log(likeArr); // Set(3) {10, 20, 30}
likeArr.delete(20);
console.log(likeArr); // Set(2) {10, 30}
//获取Set的长度
console.log(likeArr.size); // 2
// Set判断是否存在该元素
console.log(likeArr.has(30)) // true
// Set遍历:Set没有下标不能使用for-in循环遍历
for(let elem of likeArr){
console.log(elem); // 10 30
}
likeArr.forEach(item=>{
console.log(item); // 10 30
})
// 清除所有元素
likeArr.clear();
console.log(likeArr); // Set(0) {}
map:ES6提供了’值-值’对的数据结构,键名不仅可以是字符串,也可以是对象。它是一个更完善的Hash结构
let m = new Map();
// 添加元素
m.set('a',2);
m.set('b',10)
m.set('c',100)
console.log(m); // Map(3) {"a" => 2, "b" => 10, "c" => 100}
// Map也可以通过数组来传值添加元素
let m2 = new Map([['name','wq'],['age',20]]);
console.log(m2); // Map(2) {"name" => "wq", "age" => 20}
// 根据键获取元素
console.log(m2.get('name')); // 'wq'
// 获取Map元素的长度
console.log(m2.size); // 2
// 判断是否存在键
console.log(m2.has('name')); // true
// 遍历
for (let elem of m2) {
console.log(elem); // ['name','wq'] ['age',20]
}
for (let elem of m2.entries()) {
console.log(elem) // ['name','wq'] ['age',20]
}
for (let elem of m2.values()) {
console.log(elem) // wq 20
}
for (let elem of m2.keys()) {
console.log(elem); // name age
}
m2.forEach(val=>{
console.log(val) // wq 20
})
// 清除元素
m2.clear();
console.log(m2); // Map(0) {}
4.Generators函数
Generator函数是协程在ES6的实现,用来做异步流程的封装,最大特点就是可以交出函数的执行权(即暂停执行)。有点类似于浏览器中的断点执行。
function * abc(n){
yield n;
let s=5;
n+=s;
yield n;
n*=n;
yield n;
return n;
}
let gFun = abc(10);
console.log(gFun); // 并不返回数值
let gFun2 = abc(10);
console.log(gFun2.next()); // {value: 10, done: false}
console.log(gFun2.next()); // {value: 15, done: false}
console.log(gFun2.next()); // {value: 225, done: false}
console.log(gFun2.next()); // {value: 225, done: true},done为true说明已经结束
// 循环执行
let gFun3 = abc(10);
let next = gFun3.next();
while(!next.done){
console.log(next.value); // 10 15 225
next = gFun3.next();
}
5.Promise
Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码;让代码更加的直观。
function runAsync(){
let p = new Promise((resolve,reject)=>{
// 模拟异步操作
setTimeout(()=>{
resolve('执行成功了')
},2000)
})
return p;
}
runAsync().then((data)=>{ // 使用then()接受Promise返回的结果
console.log(data); // 执行成功了
});
// Promise最大的特点就是可以简化层层回调
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
resolve('数据1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
resolve('数据2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
resolve('数据3');
}, 3000);
});
return p;
}
runAsync1()
.then(function(data){
console.log(data); // 数据1
return runAsync2();
},()=>{
console.log('error'); // reject时执行的方法
})
.then(function(data){
console.log(data); // 数据2
return runAsync3();
})
.then(function(data){
console.log(data); // 数据3
});
// all的使用:一次性同时执行多个回调,并以数组返回结果
Promise.all([runAsync1(),runAsync2(),runAsync3()])
.then((result)=>{
console.log(result); // ["数据1", "数据2", "数据3"]
})
// race的使用:谁跑得快,就以谁的执行回调为准
Promise.race([runAsync1(),runAsync2(),runAsync3()])
.then((result)=>{
console.log('1212',result);
})
6.异步等待
async函数返回一个Promise对象,需要then方法获取结果
await是等待异步的意思,等待到结果再继续执行后面的代码
async function testAsync(){
return 'hello async'
}
testAsync().then(res=>{
console.log(res); // hello async
})
function async1(){
return new Promise((resolve)=>{
// 模拟异步操作
setTimeout(()=>{
resolve('模拟耗时操作');
},3000)
})
}
async function await1(){
let res = await async1();
return res+' 模拟await';
}
await1().then((res)=>{
console.log(res) // '模拟耗时操作 模拟await'
})
7.字符串扩展方法
// 查找字符串,返回布尔值
console.log('abcdef'.includes('a')); // true
// 判断是否以...开头
console.log('abcdef'.startsWith('ab')); // true
// 判断是否以...结尾
console.log('abcdef'.endsWith('ef')); // true
// 让字符串重复n次
console.log('abc'.repeat(3)); // abcabcabc
// 判断是否足够n位,不够在头部补足
console.log('abc'.padStart(5,'A')); // AAabc
// 判断是否足够n位,不够在尾部补足
console.log('abc'.padEnd(5,'A')) // abcAA