ES6常用语法

时间:2022-11-21 11:58:20


一、let、const、var

var:块级,容易污染全局
let、const:局部

1.1定义变量防止污染全局,因为他们输局部变量,var是块变量:
{
let name = "yes"
console.log(name) //yes
}
console.log(name) //window.name

1.2 for循环要使用let声明,因为这样每次循环式一个作用于,如果用var,那就是所有循环共享,const无法再for中使用,const修饰的变量
不能被修改

1.3 临时性死区
console.log(color) //undefined
var color = 'yellow'

console.log(color) //报错error
let color = 'yellow'

console.log(color) //报错error
const color = 'yellow'

【注】:es6中少用var,多用let、const,如果变量会被修改就用let,
不能修改就用const


二、箭头函数
var nums = [1,2];
//普通写法
nums.map(function(number){
return number + 1;
})
1、显示返回
//es6写法(删除function,在后面加“=>”)
nums.map((number)=>{
return number + 1;
})
2、隐式返回(return删除、大括号删除)
nums.map((number)=>number + 1)


3、箭头函数中的this是继承父级的,以往都是使用:
var _this = this;
使用箭头函数就可以直接继承父级的使用this了:
var obj = {
name:'seven',
hobbies:['coding','sleeping']
printBhobbies:function(){
this.hobbies.map((hobby)=>{
//这里的this继承父级的this
console.log(this.name+"-->"+hobby)
})
}
}

4、对象、数组解构

5、forEach(注意"E"大写)、for of:
Array.prototype.fun = function() {
console.log(99);
};
let arr = [3,4,5,6];
arr.font = 'wokao';

5.1 arr.forEach(number=>{
console.log(number)//3,4,5,6
})
//forEach无法跳过和终止(continue、break)

5.2 for(let index of arr){
console.log(arr[index])//3,4,5,6,wokao,function(){}
}

5.3 for(let number of arr){
console.log(number)
}
//for of支持continue、break,但是这样无法获取索引

for(let [index,number] of arr.entries()){
console.log(index,number)
}
//entries()是js数组迭代接口,里面通过next调用下一个,这样就可以获取索引

//for of相对于for in遍历的直接是value而不是index,其次,for in 会遍历
数组上的属性,for of只会遍历其中value,**但是需要注意的是for of目前不支持对象**


6、Array.from与Array.of:
6.1 Array.from:方法从一个类似数组或可迭代对象(字符串、对象等)中创建一个新的数组实例。
Array.from(obj);
Array.from(array,row=>{row.name}))
6.2 Array.of(2,3,4444,5,5):将穿进去的参数转变为数组

7、剩余参数 ...data:
7.1 var arr = [1,2,3,4,5];
const {a,b,...c} = arr; //a:1 b:2 c:[3,4,5]

7.2 function aa(a,...b){
console.log(a,b)
}
aa(1,2,3,4) //1 [2,3,4]

8、扩展参数
var nmn = ['a','b','c'];
var aba = ['f','n'];
var res = [...nmn,'e',...aba];//['a','b','c','e','f','n']


9、Promise:相当于一种承诺,不管怎样都会有一个结果。
9.1 对异步请求
//后一个请求依赖前一个请求,可以先定义前一个请求的promise,然后监听then,在then成功后在来第二个请求的promise,然后监听第二个请求的then
let username;
let usersPromise = axios.get('https://api.github.com/users');
usersPromise.then(response=>{
username = response.data[0].login;
return axios.get('https://api.github.com/users/'+username+'/repos');
}).then(response=>{
console.log(response.data)
}).catch(error=>{
//整个过程只要有错误就会进入此
console.log(error.response)
})

9.2 写自己的promise:

//成功就调用success数据,失败就调用error数据
const p = new Promise((success,failed)=>{
// success(' seven is a good boy!'); //reslove立即返回
setTimeout(()=>{
// success('seven is a superMan!'); //2s后执行完,进入then
failed(Error('seven is a badboy!')); //2s后进入catch,Error()可以抛出Promise中错误行,如果不加那就会显示catch下的错误行
},2000)
});

p.then(data=>{
console.log(data);
}).catch(error=>{
console.error(error);
})


9.3 多个互不相干的promise可以使用Promise.all([p1,p2,..])

//多个promise,并且之间无关联,可以使用Promise.all()调用
const users = new Promise((success,failed)=>{
setTimeout(()=>{
success([
{id:1,name:'张三'},
{id:2,name:'李四'},
])
},2000)

})

const moves = new Promise((success,failed)=>{
setTimeout(()=>{
success([
{id:1,name:'小兵张嘎'},
{id:2,name:'举起手来'},
])
},1000)

})

console.log(Promise.all([users,moves])); //返回两个数组0:users的数据 1:moves的数据


10 Symbol :javascript推出的第七种数据类型

10.1 解决对象中有相同key被覆盖情况:
var obj = {
[Symbol('user')]:{name:'张三',age:11},
[Symbol('user')]:{name:'李四',age:15,sex:'男'},
}
console.log(obj);
//Symbol(user): {name: "张三", age: 11},Symbol(user): {name: "李四", age: 15, sex: "男"}


10.2 Symbol不能被遍历:
for(let index in obj){
console.log(obj[index]);//啥也没有
}

通过js提供特殊接口获取Symbol数据:
Object.getOwnPropertySymbols(obj);//获得一个Array

提供四种遍历方法:
Object.getOwnPropertySymbols(obj).map(sym=>{
console.log(obj[sym]);
console.log(obj[sym].name);
console.log(obj[sym].age);
});

for(let sym of Object.getOwnPropertySymbols(obj)){
console.log(obj[sym]);
console.log(obj[sym].name);
console.log(obj[sym].age);
}

let newUserArr = Object.getOwnPropertySymbols(obj);
for(let index in newUserArr){
console.log(obj[newUserArr[index]]);
console.log(obj[newUserArr[index]].name);
console.log(obj[newUserArr[index]].age);
}


let userArr = Object.getOwnPropertySymbols(obj);
userArr((sym,index)=>{
console.log(obj[sym]);
console.log(obj[sym].name);
console.log(obj[sym].age);
})


11 eslint
11.1 安装
npm install eslint
npm install -g eslint

然后在命令行输入
eslint --init //初始化配置文件,选择Answer...


eslint bad-code.js //检查bad-code.js语法


11.2 排查错误:
语法查错位置:http://eslint.cn/docs/rules/
将错误规则名字(如:semi)复制,来上面链接找对应解决办法。

eslint bad-code.js --fix ; //eslint会自动修复一些错误

11.3 配置规则:.eslintrc.json
在.eslintrc.json的rules中配置:
{
....
"global":{ //定义全局变量而不报错
"Vue":true
},
"rules":{
"no-console":"error" //off(0)、warn(1)、error(2)
}
}


11.4 禁用eslint:
1)模块级禁用:在该模块上方定义
/* globals Vue */
new Vue({...})
2)区间内不用eslint限制:
/*eslint-disable 规则名(no-console) */
....这中间的代码不受eslint限制....
/*eslint-enable 规则名(no-console)*/



12 模块

12.1 导出模块
1)
//单个命名导出
export const apikey='xxx';
//批量命名导出
const a = 1;
const b = 2;
export {a as A,b} //as重命名后,外面就要使用A
2) //默认导出
const apikey = 'yyy';
export default apikey;

//引用2)方式默认导出的,在引用可以随便命名,不是用{}
import apikeysuibian from './config';
//应用1)方式必须与导出名字相同并且要用{}
import {apikey as Key} from './config';
//如果导出一个模块下a(默认导出),b,c(b,c命名导出),引用:
import a,{b,c} from './config'

tips:
[slug 插件]:将用户输入的emoji等都改为"-"连接
npm install slug --save
import slug from slug;
let name = slug(name);


13 Class改写prototype的继承

13.1 类的定义
1)class User{}
2)const User = class{}

class User{
constructor(name,age){
this.name = name;
this.age = age;
}

//普通方法,通过实例调用
info(){
console.log(this.name + ',' +this.age)
}

//静态方法用static修饰,通过类调用
static description(){
conosle.log('我是静态方法')
}

//通过set赋值
set github(value){
this.githubName = value;
}
//通过get取值
get github(){
return this.this.githubName;
}
}
const user = new User('张三',14);
user.githubName = 'seven';//触发set github()
console.log(user.githubName);//触发get github()

【注】:类中的方法与方法之间不能有",",与后端代码一样


13.2 类的扩展
1)类中的方法名称也可以使用计算属性
const methodName = 'info';
class User{
[methodName](){
return 'info method';
}
}


2)类的继承

es5类的继承:
function Animal(name,age){
this.name = name;
this.age = age;
}
function Dog(){
Animal.call(this,name,age);
this.name = name;
this.age = age;
}
Dog.prototype = new Animal();
//由于原型指向了Animal,构造也会是Animal,所以要指回来
Dog.prototype.constructor = Dog();

es6类的继承:
class Animal{
constructor(name,age){
this.name = name;
this.age = age;
}
}
class Dog extends Animal{
constructor(name,age){
super(name,age);
this.name = name;
this.age = age;
}
}

覆盖、重写:
子类与父类方法名相同就覆盖了


14 迭代器
var arr = [1,2,3];
let iter = arr[Symbol.iterator]()
iter.next() //1
iter.next() //2
..

实现数组返回value与index迭代器:
Array.prototype.values = function(){
let i = 0;
let items = this;
return {
next(){
const done = i >= items.length;
const value = done ? undefined: items[i++];
return {
done,
value
}
}
}
}

let arr = [1,2,3];
const iter = arr.values();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());

15 生成器Generator:
15.1 生成器定义以及简单实用

function* listColors(){
yield
}

/* 1 返回规定值*/
function* listColors(){
yield 'red';
yield 'yellow';
yield 'green';
}

const color = listColors();
color.next(); //red
color.next(); //yellow
color.next();//green

/* 2 返回计算值*/
function* number(){
let i = 0;
yield i;
i++;
yield i;
i++;
yield i;
i++;
}

const n = number();
console.log(n.next()) //0
console.log(n.next()) //1
console.log(n.next())//2


/* 3 返回计算的数组*/
function* loop(repos){
for(const repo of repos){
yield repo
}
}
const arr = ['a','b','c','d','e'];
const repoGen = loop(arr);
for(let repo of repoGen){
console.log(repo)
}


15.2 生成器控制ajax工作流
function ajax(url){
axios.get(url).then(res=>userGen.next(res.data));
}

function* steps(){
const users = yield ajax('https://api.github.com/users');
const firstUser = yield ajax('https://api.github.com/users/'+users[0].login);
const followers = yield ajax(firstUser.followers_url);
}

const userGen = steps();
userGen.next(); //初始化执行获取users那一步,然后通过ajax调用成功后,在调用userGen的next(res.data),
//其中res.data返回后保存在const users中,然后才执行外面的next()而执行firstUser
//....



16 proxy:proxy 重新定义对象默认属性、方法,没有改变的就默认还是用之前对象的,相当于代理模式
16.1 proxy定义:
const person = {name:"seven",age:23};
const personProxy = new Proxy(person, {
get(target,key){ //personProxy.name 触发此方法
//target:personProxy , key:name
return target[name].toUpperCase();
},
set(target,key,value){ //personProxy.name = xxx 触发此方法
//target:personProxy , key:name
return target[name] = value;
}

});
personProxy.name = 'good boy';
console.log(personProxy) //name: good boy ,age:23
//proxy 就是改变某些对象默认属性、方法,没有改变的就默认还是用之前对象的,代理模式


16.2 proxy实际应用:
1)手机号码输出格式化
const phoneHandler = {
set(target,key,value){
target[key] = value.match(/[0-9]/g).join('');
},
get(target, key){
return target[key].replace(/(\d{3})(\d{4})(\d{4})/,'$1-$2-$3');
}
}
const phoneNumber = new Proxy({},phoneHandler)
phoneNumber.number = '13247629622';
console.log(phoneNumber.number ); //132-4762-9622

17 set集合
const fruits = new Set(['apple','pear']);
const colors = new Set();
colors.add(1);
colors.add('1');
//set 无法通过索引获取,因为是无序的
//set 重复值会被替换,但是字符串1与数字1是两种

colors.delete('1') ;//删除某个元素
colors.has('1');//是否存在
colors.clear();//清除所有的set数据

//遍历set:forof 、forEach
colors.forEach((value,key,curSets)=>{
console.log(value) //第一个参数是value
console.log(key) //第二个参数说是索引,但是set无序,为了与数组forEach保持一致key也设置了value的值
console.log(curSet)//当前遍历的set集合
})


//set可以去重数组重复值
const numbers = [1,1,1,2,3,4,4,4,5];
const numbersSet = new Set(numbers); //数组转set
console.log(numbersSet);//Set(5) {1, 2, 3, 4, 5}
const uniqueNumbers = [...numbersSet]; //set转数组利用扩展参数
console.log(uniqueNumbers); //[1,2,3,4,5]


18 WeakSet
18.1 与Set区别
1)必须传入的都是对象:new WeakSet([{},{},...])
2)内部没有next不是iterator,不可用for、forEach循环
3)相对于数组存储对象而言:
数组:
let obj1 = {'name':'aa',age:11};
let obj2 = {'name':'bb',age:22};
let arr = [obj1,obj2]
obj1 = null;
console.log(arr);
//[{'name':'aa',age:11},{'name':'bb',age:22}]

WeakSet集合
let obj1 = {'name':'aa',age:11};
let obj2 = {'name':'bb',age:22};
let weakSetData = new WeakSet([obj1,obj2]);
obj1 = null;
console.log(weakSetData);
//obj1就不存在了

【注】通过这一点可以判断引用是否被清除


19 Map

const fruits = new Map([['apple',5],['banana',6]]);
const map = new Map();
const map = new Map();
map.set('a',233);
map.set('b',233);
console.log(map);

//map相对于对象来说,key可以是任意的(可以是对象)
console.log(map.size);
console.log(map.has('a'));
map.delete('a');//删除
map.clear(); //清空
console.log(map.get('a'));//单独取某个值

//可以通过for、forEach循环
map.forEach((value,key,map)=>{
console.log(value);
console.log(key);
console.log(map);
})

for(let [key,value] of map){
console.log(key)
console.log(value)
}

20 WeakMap
与map区别:
1)没有size属性
2)没有clear方法
3)不能通过for循环
4)key必须是对象
5)与WeakSet类似,如果内部对象没有被引用了,辣鸡回收机制就会回收该对象。


let obj1 = {name:'zz'};
let obj2 = {name:'yy'};

let map1 = new Map();
map1.set(obj1,'this is map1 obj1');
map1.set(obj2,'this is map1 obj2');
let map2 = new WeakMap();
map2.set(obj1,'this is map2 obj1');
map2.set(obj2,'this is map2 obj2');

obj1 = null;

console.log(map1);
console.log(map2);