前言:希望可以通过这篇文章,能够给你得到帮助。(感谢一键三连),前端小白不断升级打怪中...
1. let const
{} // 块级作用域
for if while // 都是块级作用域
没有预解析,不存在变量提升 在代码块内,只要let定义变量,在之前使用报错(先定义,再使用)
function show(){
console.log(a);
let a = 3; //报错
}
不能重复定义变量(同一个作用域) for循环for循环里面是父级作用域,里面又一个作用域
for(let i=0;i<3;i++){ // 两个作用域
let i= 'abc';
console.log(i);
// abc abc abc
}
暂时性死区 const 特性和let一样 const 常量不能修改 const定义完变量,必须有值,不能后赋值
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
对象引用可以修改 例如:
const arr = [1,2,2];
arr.push(3);
// 1,2,2,3
Object.freeze([1,2,3]) //不能修改
(function(){
})() //用来模拟作用域
2. 结构赋值
注意:左右两边,结构保持一致
let [a,b,c] = [12,5,6];
let [a='默认值',b,c] = [12,5];
let [a,b,c:'默认值'] = [12,5,null]; c = null
let a= 12;
let b= 5;
[a,b] = [b,a]; a = 5,b = 12
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
json 对象结构
let json = {
name: 'xxx',
age: 18
}
let {name,age} = json;
console.log(name,age);// xxx 18
let {name:n,age} = json; //n别名
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined
如果变量名与属性名不一致,必须写成下面这样。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
字符串的解构赋值 解析时候可以给默认值 传参也可以结构
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let {length : len} = 'hello';
len // 5
3. 字符串模板
优点:随意换行
`${}`
let name = 'xxx';
let age = 18;
let str = `这个人叫${name},年龄是${age}`
字符串方法 查找
indexOf('') // 返回索引位置
str.includes(要找的东西) //返回true/false
str.startswith() // 以xxx开头
str.endswith() // 以xxx结尾
str.repeat(n) // 重复多少次
str.padStart(整个字符常长度,填充的东西) // 往前填充
str.padEnd() //往后填充
4. 函数
函数默认参数
function show(x='默认值',y='默认值'){
console.log(x,y);
};
show('','a');
show('b');
*结构
function show({x=0,0}={}){
console.log(x,y);
};
show({x:1,y:7});
show();
函数参数默认已经定义,不能再使用let,const声明
function show(x=18){
let x=101; //报错
}
show();
扩展运算符 Rest运算符 ... //扩展运算符 即展开又可以重置 展开数组
let arr = [1,2,3];
console.log(arr); //[1,2,3];
console.log(...arr);
// 1,2,3
合并
function show(...a){
console.log(a) //[1,2,3,4,5]
}
show(1,2,3,4,5)
类似
function show(){
let a = Array.prototype.slice.call(arguments);
console.log(a); // [1,4,5,2,9,4]
}
show(1,4,5,2,9,4);
剩余运算符 展开数组 [1,2,3]->...[1,2.3]->1,2,3 重置 1,2,3-> ...1,2,3 -> [1,2,3] 剩余参数:必须放到参数最后
function show(a,b,...c){
// a = 1,
// b = 2,
// c= [3,4,5]
}
show(1,2,3,4,5)
let arr = [1,2,3];
let arr2 = [...arr]; // [1,2,3]
或者 let arrs = Array.from(arr); // [1,2,3]
let str = 'a b c'; let arrs = Array.from(str); // ['a','b','c']
箭头函数 注意: 1.this问题,定义函数所在的对象,不再是运行时所在的对象 2.箭头函数没有arguments,用... 3.箭头函数不能当构造函数
let show = () => 1;
console.log(show()); // 1
() => {
语句
}
let show = (a=12,b=8)=>{
console.log(a);
return a*b;
}
let json = {
id: 1,
show:function(){
alert(this.id); // 1
}
}
json.show();
let json = {
id: 1,
show:function(){
setTimeout(function(){
alert(this.id); // undefined
},200)
//setTimeout是用window执行的,
window没有id
}
}
json.show();
var id = 10;
let id = 10; //如果是let定义也是undefined
let json = {
id: 1,
show:function(){
setTimeout(function(){
alert(this.id); // 10
},200)
}
}
json.show();
let json = {
id: 1,
show:function(){
setTimeout(()=>{
alert(this.id); // 1
},200)
}
}
json.show();
var id= 6;
let json = {
id: 1,
show:function(){
setTimeout(()=>{
let id = 10;
alert(this.id); // 1
},200)
}
}
json.show();
var id= 6;
let json = {
id: 1,
show:()=>{
alert(this.id) // 6
setTimeout(()=>{
let id = 10;
alert(this.id); // 6
},200)
}
}
json.show();
let id= 6;
let json = {
id: 1,
show:()=>{
alert(this.id) //undefined
setTimeout(()=>{
let id = 10;
alert(this.id); // undefined
},200)
}
}
json.show();
5. 数组
for循环 2.while / /es5新增 (forEach,map,filter,some,every,reduce,reduceRight)
arr.forEach()
// 以下他们可以接受两个参数(循环回调函数,this指向谁)
let arr=[1,2,3];
for(let i = 0;i < arr.length; i++){
}
arr.forEach()//代替普通for循环
arr.forEach(function(val,index,arr){
console.log(this)//456 this指向456
},456);
// 箭头形式
arr.forEach((val,index,arr)=>{
console.log(this)// this指向window
},123);
// 箭头函数this指向定义时 window
arr.map() 非常有用,做数据交互,‘映射’ 正常情况下,需要配合return,返回是一个新数组,如果没有return,相当于forEach 注意:平时用map,一定要有return;
let newArr = arr.map((item,index,arr)=>{
return item;
});
newArr = [1,2,3];
arr.filter()
let arr = [{title:'111',hot: false},
{title: '222',hot:true},{title:'333',hot:false}]
let newArr = arr.filter((item,index,arr){
return item.hot === true;
});
console.log(newArr);
// [{title: '222',hot:true}]
arr.some() 类似查找,数组里面某一个元素符合,返回true //过滤 过滤一些不合格,如果回调函数返回true,就留下来
let arr = ['aa','bb','cc'];
let back = arr.some((item,index,arr)=>{
return item === 'aa'
});
console.log(back)//true
arr.every() 数组里面所有的元素都要符合条件,才返回true
arr.reduce() 从左往右 //求数组的和,阶乘 接收的参数与其他不同
let arr = [1,2,3,4,5,6,7,8,9,10];
let res = arr.reduce((prev,cur,index,arr)=>{
return prev+cur;
});
// 55 prev上一个结果,cur当前值
arr.reduceRight() //从右往左
// for----of
let arr = ['aaa','bbb','ccc'];
for(let val of arr){
console.log(val) //
aaa bbb ccc
}
for(let index of arr.keys()){
console.log(index) //
0 1 2
}
for(let item of arr.entries()){
console.log(item) //
[0,'aaa'] item[0] 1 item[1] aaa
[1,'bbb']
[2,'ccc']
}
for(let [key,val] of arr.entries()){
console.log(key,val);//
0 aaa
1 bbb
2 ccc
}
Array.from() 作用:把类数组(获取一组元素,arguments....)对象转成数组 个人观点:具备length这东西就靠谱
[].slice.call(arr) //ES5之前的方法 Array.from(arr)//ES6方法 [...arr]//ES6方法
let str = "stri";
Array.from(str) // ['s','t','r','i'];
let json = {
0:'aa',
1: 'bb',
2: 'cc'
}
Array.from(json) //不行
let json = {
0:'aa',
1: 'bb',
2: 'cc',
length: 3
}
Array.from(json) // ['aa','bb','cc']
let json = {
0:'aa',
1: 'bb',
2: 'cc',
length: 2
}
Array.from(json) // ['aa','bb']
Array.of() 把一组值转成数组
Array.of('aa','bb')
// ['aa','bb']
arr.find() 查找找出第一个符合条件的数组成员,如果没有找到,返回undefined
let arr = [23,59,900,200];
let res = arr.find((val,index,arr)=>{
return val > 100; // 900
});
arr.findIndex() 找的是位置,没找到返回-
let arr = [23,59,900,200];
let res = arr.find((val,index,arr)=>{
return val > 100; // 2
});
arr.fill(填充的东西,开始位置,结束位置)
let arr = new Array(10);
arr.fill('默认值')
['默认值',...]
arr.includes() 在ES2016里面新增 类似 arr.indexOf()返回索引
let arr = [1,2,3];
arr.includes(1) // true
let a=new Set([1,2,3]);
let b=new Set([4,3,2]);
//交集
let union= [...new Set([...a,...b])];
console.log(union);
//并集
let intersect= [...new Set([...a].filter(x=> b.has(x)))];
console.log(intersect);
//差集
let difference= [...new Set([...a].filter(x=> !b.has(x)))];
console.log(difference);
对象
let name='aaa';
let json={
name,
show(){//个人建议,一定注意,不要箭头函数
return this.name //'aaa'
}
}
let name='aaa';
let json={
name,
show()=>{//个人建议,一定注意,不要箭头函数
return this.name //没值
}
}
Object.is() 用来比较两个值是否相等
console.log(Object.is(NaN,NaN)//true
console.log(+0 == -0)//true
console.log(Object.is(+0,-0))//false
Object.assign(目标对象,source1,source2) 1.用来合并对象 用途: 1.复制一个对象 2.合并参数
let json = {a:1};
let json2 = {b:2};
let json3 = {c:3};
Object.assign({},json,json2,json3);
// {a:1,b:2,c:3}
let json4 = {b:2,a:2};
Object.assign({},json4,json3);
//{a:2,b:2,c:3}
//2.
let arr = ['aa','bb','cc'];
Object.assign([],arr);
//['aa','bb','cc']
Object.keys() Object.values() Object.entries()
let json = {
a:1,
b:2,
c:3
}
for(let key of Object.keys(json)){
console.log(key) // a b c
}
for(let value of Object.values(json)){
console.log(value) // 1 2 3
}
//或者这么写 解构
let {keys,values,entries} = Object;
for(let item of entries(json)){
console.log(item)
// ['a':1] ['b':2] ['c':3]
}
for(let [key,value] of entries(json)){
}
对象身上:计划ES2018引入 ... 扩展复制等
let {x,y,...z} = {x:1,y:2,a:3,b:4}
// x:1
y:2
{a:3,b:4}
let json = {a:3,b:4};
let json2 = {...json};
// a:3 b:4
6. Promise
作用:解决异步问题 传统方式,大部分用回调函数,事件
ajax(url,{ //获取token
ajax(url,{ //获取用户信息
.... //获取用户相关信息
})
})
语法
let promise = new Promise(function(resolve,reject){
// resolve 成功调用
// reject 失败调用
});
promise.then(res=>{
},err=>{
});
promise.catch(err=>{//reject,发生错误别名
console.log(err)
});
或者
promise.then(res=>{
}).catch(err=>{
});
let a = 10;
let promise = new Promise((resolve,reject){
if(a===10){
resolve('成功')
}else{
reject('失败')
}
});
promise.then(res=>{
console.log(res);
},err=>{
console.log(res);
});
Promise.resolve('aa'):将现有的东西,转成一个Promise对象,resolve状态,成功状 态 Promise.reject('bb'):将现有的东西,转成一个Promise对象,reject状态,失败状态
let p = Promise.resolve('aa');
p.then(resolve=>{
resolve('aaa')
})
Promise.all([p1,p2,p3]); 把Promise打包,扔到数组里面,打包完还是一个 Promise对象必须确 保,所有的promise对象,都是resolve状态,都是成功的状态
let p1= Promise.resolve('aaa');
let p2 = Promise.resolve('bbb');
let p3= Promise.resolve('ccc');
Promise.all([p1,p2,p3]).then(res=>{
let [res1,res2,res3] = res;
console.log(res1,res2,res3)
})
Promise.race([p1,p2,p3]); 只要有一个resolve,就返回
let p1= Promise.reject('aaa');
let p2 = Promise.reject('bbb');
let p3= Promise.resolve('ccc');
Promise.all([p1,p2,p3]).then(res=>{
let [res1,res2,res3] = res;
console.log(res1,res2,res3)
}).catch(res=>{
});
用户登录->用户信息
let status = 1;
let userLogin = (resolve,reject)=>{
setTimeout(()=>{
if(status ===1){
resolve({data:'登录成功,age:xx})
}else{
reject('失败')
}
},2000)
}
let getUserInfo = (resolve,reject)=>{
setTimeout(()=>{
if(status ===1){
resolve({data:'获取用户信息,age:xx})
}else{
reject('失败')
}
},1000)
}
new Promise(userLogin).then(res=>{
console.log('用户登录成功');
console.log(res);
return new Promise(getUserInfo);
}).then(res=>{
console.log('获取用户信息成功')
console.log(res);
})
//用户登录成功
// {data: xxx}
// 获取用户信息成功
// {data: '获取用户信息'}
7. 模块化
js不支持模块化 在ES6之前,社区制定一套模块规范 Common.js 主要服务端 node.js require('http') AMD requireJs ,curlJs ,seaJs ES6出来,同意服务端和客户端模块规范 import {xxx} ddd;
使用模块( 注意放到服务器环境 ) 1.如何定义模块 export const a = 1; 2.如何使用 import './module/1.js'
<script type ="module">
import './module/1.js'
</script>
1.js
console.log('模块加载了')
export const a = 1;
或者
const a = 1;
const b = 2;
export {
a,
b as c // 别名
}
import特点 :可以是相对路径,也开始绝对路径
import {a as x, c} from './module/1.js';
import 模块只会导入一次,无论引入多少次
- import './module/1.js' 相对于引入文件
- 有提升效果,import会自动提升到顶部,首先执行
- 导出去模块内容,如果里面有定时器更改,外面也会改动,不像Common规范缓存
- import() 类似node里面require,可以动态引入;
- 默认import语法不能写到if之类里面 返回值是个Promise对象
- 优点: 按需加载 可以写if中 路径也可以动态
<script type ="module">
import {a as x, c} from './module/1.js';
console.log(x,c) //
//模块加载了
1 2
import * as mode from './module/1.js';
mode.a // 1
</script>
exprot default a = 12; // 不用{}需要定义default
import a from './module/2.js';
a // 12
3.js
const a= 12;
const b = 5;
或者import {a,b} from './module/1.js';
const sum = ()=>{
return a+b;
}
const show = ()=>{
return 'aaa'
}
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
}
export {
a,b,sum,show
}
export default {
Person
}
console.log(a,b) // 12 5 // 有提升效果
import mode,{show,sum,a,b} from './module/3.js';
let p = new node.Person('xx');
show(); //aaa
sum(); // 17
console.log(a,b) // 12 5
p.showName() // xx
import() 例子
let a = 12;
if(a===12){
import {a} from './module/1.js';
}else{
import {b} from './module/2.js';
}
// 错误的
import('./module/1.js').then(res=>{
console.log(res.a) // 12
})
返回值是个Promise对象 优点: 1.按需加载 2.可以写if中 3.路径也可以动态 Promise.all()
Promise.all(['./1.js','./2.js']).then([mode1,mode2])=>{
})
ES2017 加 async wait
async function main(){
const mode1 = wait import('./1.js');
const mode2 = wait import('./1.js');
const [m1,m2] = wait Promise.all([mode1,mode2]).then([import('./1.js'),import('./2.js')]);
console.log(m1,m2);
}
main();
'use strict' 严格模式
8. class
ES5之前是通过函数模拟
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.showName = function(){
return this.name;
}
或者
object.assign(Person.prototype,{
showName(){
return this.name;
},
showAge(){
return this.age;
}
});
let p = new Person('strive',18);
p.showName(); // strive
ES6写法: 1.class没有提升功能,没有预解析,在ES5用函数模拟可以,默认函数提升 2.this比之前轻松多了
class Person{
//构造函数,调用new ,自动执行
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
}
new Person('strive',age);
或者这么定义 不推荐使用
const Person = class{
//构造函数,调用new ,自动执行
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
}
let show = 'other';
let show1 = 'uuu';
const Person = class{
//构造函数,调用new ,自动执行
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
},
show(){
console.log('xxx');
},
[show1](){
console.log('yyy');
}
[show+show1](){
}
}
let p = new Person('strive',18);
p.show() // 'xxx'
p.show1() // undefined
p[show1]() // 'yyy'
矫正this 1.fn.call(this指向,arg1,arg2...) 2.fn.apply(this指向,[arg1,arg2...]); 3.fn.bind();
class Person{
constructor(){
this.name = 'strive';
this.showName = this.showName.bind(this);
}
showName(){
return this.name;
}
}
let p =new Person();
let {showName} = p;
console.log(showName())//报错
可以用 this.showName = this.showName.bind(this); //矫正
class里面取值函数(getter),赋值(setter)
class Person(){
constructor(){
}
get aaa(){
return `aaa的属性`
}
set aaa(val){
console.log(val) //111
}
}
let p = new Person();
p.aaa = '111';
console.log(p.aaa)//111的属性
静态方法:就是类身上的方法
static fn(){}
静态方法可以由子类继承
class Person(){
constructor(){
}
showName(){
}
static show(){
return '这是静态方法'
}
}
let p = new Person();
p.showName();
Person.show();
父类子类 继承之前的方法
//父类
function Person(name){
this.name = name;
}
Person.prototype.showName = function(){
return this.name;
}
//子类
function Student(name,skill){
Person.call(this,name);//继承属性
this.skill = skill;
}
Student.prototype = new Person();//通过继承方法
调用
let stu = new Student('strive','逃学');
stu.showName();
ES6继承 extends
// 父类
class Person(){
constructor(name){
this.name = name;
}
showName(){
console.log('父类')
}
}
// 子类
class Student extends Person{
constructor(name,skill){
super(name);//父类构造函数
this.skill = skill;
}
showName(){
super.showName()//父类方法执行
console.log('子类')
}
show(){
console.log(this.name,this.skill)
}
}
let stu = new Student('xxx','yyy');
stu.skill // yyy
stu.show() // xxx yyy
stu.showName(); // 父类 子类
拖拽
<div id="div1"></div>
<div id="div2"></div>
class Drag{
constructor(id){
this.oDiv = document.querySelector(id);
this.disX = 0;
this.disY = 0;
this.init();
}
init(){
this.oDiv.onmousedown = function(ev){
this.disX = ev.clientX - this.oDiv.offsetLeft;
this.dixY = ev.clientY - this.oDiv.offsetTop;
document.onmousemove = this.fnMove.bind(this);
document.onmouseup = this.fnUp.bind(this);
return false;
}.bind(this);
}
fnMove(ev){
this.oDiv.style.left = ev.clientX-this.disX +'px';
this.oDiv.style.top = ev.clientY-this.disY+'px';
}
fnUp(){
document.onmousemove = null;
document.onmouseuo = null;
}
}
//子类
class LimitDrag extends Drop{
fnMove(ev){
super.fnMove(ev);
//限制范围
if(this.oDiv.offsetLeft <= 0){
this.oDiv.style.left = 0;
}
}
}
//new Drag('#div1'); //能拖出去
new LimitDrag('#div2');//限制拖出去
9. Symbol
数据类型
// number string boolean Object undefined function
// 用typeof 检测出来数据类型
Symbol
new Number(12)
Symbol使用一般 注意: 1、Symbol不能new 2、Symbol()返回是一个唯一值(房建传说,做一个key,定义一些唯一或者私有) 3、Symbol是一个单独数据类型,就叫Symbol基本类型 4、如果Symbol作为key,用for in 循环不出来
let syml = Symbol('aaa);
let syml = Symbol('strive);
let json = {
a: 'aa',
[symbol]:'bbb'
}
json[a] //aa
json[symbol] //bbb
for(let key in json){
console.log(key) //a 4、如果Symbol作为key,用for in 循环不出来
}
10. generator函数
解决异步问题,深度嵌套的问题 语法
function * show(){
yield
}
function * show(){
yield 'aaa'
yield 'bbb'
return 'ccc'
}
//调用
let sh = show()
console.log(sh) // 返回对象
console.log(sh.next())//{value: "aaa", done:false}
console.log(sh.next())//{value: "bbb", done:false}
console.log(sh.next())//{value: "bbb", done:true}
console.log(sh.next())//{value: undefined, done:true}
//以上调用,手动调用,麻烦
for...of自动遍历generator,return的东西。它不会遍历
for(let val of sh){
cosole.log(val)
}
// generator不仅可以配合for...of还可以结构赋值
function * show(){
yield 'aaa'
yield 'bbb'
yield 'ccc'
return 'ddd'
}
let [a,b,c,d] = show();
// aaa bbb ccc undefined
let [a,...b] = show();
//aaa ['bbb', 'ccc']
// 扩展运算符
...show() // aaa bbb ccc
Array.from(show()) ['aaa','bbb','ccc']
generator结合axios数据请求
function * gen(){
let val = yeild 'strive';
yield axios.get(''http://.../${val});
}
let g = gen();
let userName = g.next().value;
//g.next(userName).value -->promise
g.next(userName).value.then(res=>{
console.log(res.data);
});
异步:不连续,上一个操作没有执行完,下一个操作照样开始。 同步:连续执行,上一个操作没有执行完,下一个没法开始。 关于异步,解决方案: 1.回调函数 2.事件监听 3.发布/订阅 4.Promise对象
ES2017,规定async
11. async
const fs = require('fs');
//简单封装 fs封装成promise版本
const readFile = function (filename){
return new Promise(resolve,reject)=>{
fs.readFile(filename,(err,data)=>{
if(err) reject(err);
resolve(data);
})
}
}
//promise
readFile('data/a.text').then(res=>{
console.log(res.toString());//aaa
return readFile('data/b.txt');
}).then(res=>{
console.log(res.toString())// aaa bbb
})
genertaor
function *gen(){
yield readFile('data/a.txt');
yield readFile('data/b.txt');
yield readFile('data/c.txt');
}
let g = gen();
g.next().value.then(res=>{
console.log(res.toString());
return g.next().value;
}).then(res=>{
console.log(res.toString());
return g.next().value;
}).then(res=>{
console.log(res.toString()) // aaa bbb ccc
})
async
async function fn(){
let f1 = await readFile('data/a.txt');
console.log(f1.toString());
let f2 = await readFile('data/b.txt');
console.log(f2.toString());
let f3 = await readFile('data/c.txt');
console.log(f3.toString());
}
async特点: 1.await 只能放到async函数里 2.相比generator语义化更强 3.await后面可以是promise对象,也可以数字、字符串、布尔 4.async函数返回是一个promise对象 5.只要await语句后面promise状态变成reject,那么整个async函数中断执行 如何解决async函数中抛出错误,影响后续代码 a)try{ }catch(e){ } b)promise本身catch 个人建议:只要await 都try catch
async function fn(){ //表示异步,这个函数里面有异步任务
await //表示后面结果需要等待
}
//async
async function fn(){
return 'aaa';
}
fn() //Promise
fn().then(res=>{
console.log(res) // aaa
})
async function fn(){ //表示异步,这个函数里面有异步任务
await //表示后面结果需要等待
}
//async
async function fn(){
throw new Error('出错了')
}
fn() //Promise
fn().then(res=>{
console.log(res)
}),err=>{
console.log(err);//出错了
}
// 或者
fn().then(res=>{
console.log(res)
}).catch(err=>{
console.log(err); //出错了
})
async function fn(){
awiat Promise.reject('出错了')
//可以try catch
try{
awiat Promise.reject('出错了')
}catch(e){
}
//也可以promise catch
awiat Promise.reject('出错了').catch(err=>{
console.log(err)
})
let a = await Promise.resolve('aaa');
}
fn().then(res=>{
console.log(res) // aaa
}).catch(err=>{
console.log(err)
})
12. Set 和WeakSet
数据结构:数组,json,二叉树.... set数据结构,类似数组,但里面不能有重复值 用法:new Set(['a','b']); key和value一样 如果 new Set({})//报错 但通过add方式是可以的{}
let arr = new Set(['a','b','c']);
//{'a','b','c'}
let setArr = new Set();
setArr.add('a') //添加
setArr.add('b') //添加
setArr.delete('a')//删除
setArr.has('a') // false //判断里面有没有此值
setArr.size() //个数
setArr.clear()//清除所有
// 循环
for...of
for(let item of setArr){//默认是values
// a b
}
for(let item of setArr.keys()){
// a b
}
for(let item of setArr.values()){
// a b
}
for(let item of setArr.entries()){
// ['a':'a'] ['a':'b']
}
for(let [k,v] of setArr.entries(){
k->a v->a
}
setArr.forEach(value,index)=>{
value->a index->a
});
// 去重
let arr = [1,2,3,2,1];
let s = new Set(arr);
Array.form(s);
// 或者
[...new Set(arr)];
set数据结构变成数组
[...set]
想让set使用数组的map filter先变成数组
let arr1 = [...new Set(arr)];//set->arr
let set = new Set(arr1)//arr->set
WeakSet()存储json 初始里面添加东西是不行的,最好用add添加 WeakSet({})这样写不行报错 weakSet没有size,没有clear,有add,has ,delete
let json = {
a:1,
b:2
}
let wSet = new WeakSet();
wSet.add(json);//{a:1,b:2}
13. Map和WeakMap
类似json,但是json的键(key)只能是字符串 map的key可以是任意类型 new Map();
let map = new Map();
let json = {
a:1,
b:2
}
map.set('a','aaa');
map.set(json,'aaa');
map.set('b',json); //设置值
map.get(json) //获取 'aaa'
map.delete(key)//删除
map.has(key)//判断有没有
map.clear()//清除所有
//循环:
for(let [key,val] of map){//默认是entries
}
for(let key of map.keys()){
}
for(let val of map.values()){
}
map.forEach((value,key)=>{
// aaa a
}
WeakMap(): key只能是对象
let wMap = new WeakMap();
let json = {
a:1,
b:2
}
wMap.set(json,'aaa');
wMap.set('aa','nn');//报错
14. 数字变化和Math新增的东西
数字(数值)变化
// 二进制:(binnary) 0b开头
let a = 0b010101;
a//21
// 八进制:(octal) 0o开头
let a = 0o666;
a //
//十六进制:
// 数字变化
let a = 2;
isNaN(a)//false
Number.isNaN(a)//false
Number.isFinite(a)//true //判断是不是数字
Number.isInteger()//判断数字是不是整数
Number.parseInt()
Number.parseFloat()
安全整数: 安全整数:-(2^53-1)到2^53包含-(2^53-1)和2^53 Number.isSafeInteger()
let a = 2**53
Number.isSafeInteger(a) //安全整数
Number.MAX_SAFE_INTEGER //最大安全整数
Number.MIN_SAFRE_INTEGER //最小安全整数
Math:
Math.abs()
Math.sqrt()
....
新增
Math.trunc()//截断
Math.trunc(4.56)//4 截断截取,只保留整数部分
Math.sign(-50) //判断一个数到底是正数、复数、0
-50->-1
50->1
0->0
-0->-0
其他值->NaN
Math.cbrt(27) // 3 计算一个数立方根
15. ES2018
命名匹配
let str = "2018-03-20";
let reg = /(\d{4})-(\d{2})-(\d{2})/;
let dateArr = str.match(reg);
let year = dateArr[1]; //2018
let month = dateArr[2];//03
let day = dateArr[3];//20
1.命名捕获
// 语法:(?<名字>)
let str = '2018-03-20';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let {year,month,day} = str.match(reg).groups;
// 2018 03 20
反向引用:
// \1 \2 $1 $2
// 反向引用命名捕获:
// 语法:\k<名字>
let reg = /^(?<strive>welcome)-\k<strive>$/;
reg.test('a-a'); //false
reg.test('welcome-welcome')//true
let reg = /^(?<strive>welcome)-\k<strive>$-\1$/;
reg.test('welcome-welcome-welcome')//true
2.替换
// $<名字>
let str = '2018-03-20';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
str.replace(reg,'$<year>/$<month>/$<day>')
//str-> 2018/03/20
str.replace(reg,'$<day>/$<month>/$<year>')
//20/03/2018
str.replace(reg,(...args)=>{
let {year,month,day} = args[args.length-1];
return `${year}/${month}/${day}`
})
dotAll模式----s 之前 '.'在正则里表示匹配任意东西,但是不包括\n
let reg = /^\w+.\w+$/s;
let str = 'welcome-51mmr';
let str2 ='welcome\n51mmr'; //true
console.log(reg.test(str));//true
标签函数
function fn(){
}
fn();//普通函数调用
function fn(args){
console.log(args);//['welcome',row:Array[1]]
return args[0].toUpperCase();
}
fn`welcome` //WELCOME
16. Proxy
代理:扩展(增强)对象一些功能: 作用:比如vue中拦截 预警、上报、扩展功能、统计、增强对象等 proxy是设计模式一种,代理模式 语法:
new Proxy(target,handle)
new Proxy(被代理的对象,对代理的对象做什么操作)
handle
{
set(){},//设置的时候干的事
get(){},//获取干的事
deleteProperty(){},//删除 'xxx' in target
has(){},//问你有没有这个对象
apply(){},// 调用函数处理
....
}
例子
let obj = {
name: 'strive'
}
let newObj = new Proxy(obj,{
get(target,property){
return target[property]
}
})
newObj.name // strive
访问一个,访问一个对象身上属性,默认不存在给underfined, 希望如果不存在错误(警告)信息
let newObj = new Proxy(obj,{
get(target,property){
if(property in target){
return target[property];
}else{
console.warn(`${property}不在属性上`)
}
}
})
DOM.div()
const DOM = new Proxy({},{
get(target,property){
//property DOM.xxx里面的xxx
return function(attr={},...chidlen){
const el = document.createElement(property);
for(let key of Object.keys(attr)){
el.setAttribute(key,attr[key]);
}
for(let child of children){
if(tyoeof child === 'string'){
child = document.createTextNode(child);
}
el.appendChild(child);
}
return el; //<div id="div1" class="aaa">我是divhhh</div>
}
}
});
let oDiv = DOM.div({id:'div1',class:'aaa'},'我是div','hhh');
set()设置拦截
let obj = new Proxy({},{
set(target,property,value){
if(property == 'age'){
if(!Number.isInteger(value)){
throw new TypeError('年龄必须为整数');
}
if(value>200){
throw new RangeError('年龄超标了');
}
}
target[property] = value;
}
})
obj.a =123;
obj.age = 202;//
deleteProperty()删除
has()
let json = {
a:1,
b:2
}
let newJson = new Proxy(json,{
deleteProperty(target,property){
delete target[property];
},
has(target,property){
return property in target;
}
});
'a' in newJson // true
delete newJson.a; // {b:2}
Reflect反射 Object.xxx语言内部方法 Object.defineProperty放到Reflect对象身上,通过Reflect对象身上直接拿到语言内部对象
apply()拦截方法
function fn(){
return '我是函数';
}
let newFn = new Proxy(fn,{
apply(){
return '函数吗?'
}
});
newFn(); //函数吗 fn被拦截里面内容不执行
Reflect反射
Reflect.apply(调用的函数,this指向,参数数组)
fn.call()
fn.apply()类似
function sum(a,b){
return a+b;
}
let newSum = new Proxy(sum,{
apply(target,context,args){ //sum函数,this指向,参数数组
return Reflect.apply(...arguments);
}
})
newSum(2,3); //5
Math.cell(4.5)//5
Reflect.apply(Math.cell,null,[9.8])//10
function show(...args){
console.log(this);
console.log(args);
}
show(1,2,3)// Window [1,2,3]
show.call('abc',[1,2,3])// -->abc [1,2,3]
show.apply('abc',[1,2,3])//--> abc [1,2,3]
Reflect.apply(show,'aaa',[1,2,3])// -->aaa [1,2,3]
//Object.xxx语言内部方法
//Object.defineProperty放到Reflect对象身上,
//通过Reflect对象身上直接拿到语言内部对象
'assign' in Object
Reflect.has(Object,'assign')//true
let json = {
a:1,
b:2
}
delete json.a // {b:2}
Reflect.deleteProperty(json,'a')//{b:2}