let const
let 定义变量,局部作用域,没有变量提升,只能先定义后使用,不能重复定义
const 定义常量,不能修改,如果定义的是一个对象,让这个对象不能修改,需要使用
Object.freeze(obj);
var 定义的全局变量是属于window的,let const 不同
解构赋值:
两边的结构格式必须一致:
demo1:
let [a,b,c]=[1,2,3];
console.log(a,b,c);//"1" "2" "3"
部分赋值
let [a1,,c1]=[1,2,3];
console.log(a1,c1);//"1" "3"
demo2:
let{name,age,job}={ name:'zhangsan',age:'12',job:'web' };
console.log(name,age,job);//"zhangsan" "12" "web"
解构赋值可以重命名:
let{name1:n,age1:g,job1:j}={ name1:'zhangsan',age1:'12',job1:'web' }; console.log(n,g,j);//"zhangsan" "12" "web"
可以设置默认值
let [d,e,f=100]=[1,2]; console.log(d,e,f);//1 2 100
交换两个值:
let a=10; let b=5; [a,b]=[b,a]; console.log(a,b);//5,10
对象再次赋值:需要用()包裹,否则会解析为局部作用域
let c='age'; ({c}={c:'name'}); console.log(c);//name
字符串模板
let name='zhangsan'; let age=15; console.log(`姓名:${name},年龄:${age}`);//姓名:zhangsan,年龄:15
1 可以随意换行 2 取值 ${}
字符串的方法:
判断是否包含某个字符串
includes() 返回true false
indexOf() 返回索引位置
字符串以谁开始:
startsWith()返回true false
字符串以谁结束:
endsWidth()返回true false
字符号重复:
repeat(次数)//重复的次数
字符号填充:
padStart(字符号长度,填充的字符串)
padEnd(字符号长度,填充的字符串)
函数默认参数 箭头函数 剩余参数
function demo({name='zhangsan',age='18'}={}){ console.log(`姓名:${name},年龄:${age}`); } demo();// demo({name:'lisi'});//姓名:lisi,年龄:18 demo({age:100})//姓名:zhangsan,年龄:18 demo({name:'lisi',age:200});//姓名:lisi,年龄:200
函数的参数默认是定义过的,不能再函数体重重复定义变量
function demo(a){
let a=100;
}
报错,变量重复定义
箭头函数,
1 this问题,定义函数所在的对象,不再是运行时所在的对象(如果不会箭头函数,this执行运行时所在的对象)
2 箭头函数内没有arguments,使用...
3 箭头函数不能用于构造函数
demo
function demo3(){ let obj= { id:2, show:function(){ setTimeout(function(){ alert(this.id);},1000); } }; return obj; } demo3().show()//undefined setTimeout是window执行的,所以this指向winidow function demo3(){ let obj= { id:2, show:function(){ setTimeout(()=>{ alert(this.id);},1000); } }; return obj; } demo3().show()//2 箭头函数,this指向定义时的对象,就是obj
... 扩展运算符 Rest运算符
数组
arr.forEach(function(val,idnex,arr){}) 参数是个回调函数,替换普通的for循环
arr.map() 做数据交互映射,重新整理数据解构,正常情况下需要配合return使用,如果没有就和forEach()一样
注意:平时用到map,就需要用到return 返回一个新的数组
arr.filter()
过滤一些不合格的元素,如果回调函数返回的是true就留下,false就过滤掉
arr.some()
遍历数组,类似查找,有一个符合要求就返回true
arr.every()
遍历数组,所有元素符合要求就返回true,否则返回false
以上的方法接收的参数都是一样的,可以接收两个参数,循环回调函数,this指向谁;
也可以使用bind修改this的指向 arr.forEach().bind(123)
arr.reduce(function(prev,cur,index,arr){}) 从左到右
求数组的和prev:上次循环的结果,cur当前的值,index当前值得索引,arr数组本身
demo:
[1,2,3,4,5].reduce((prev,cur,index,arr)=>{return pre+cur})//15
arr.reduceRight() 从右到左
for...of....
可以用来循环数组和对象 arr.keys() arr.entries()
Array.from:
把类数组转换成数组,类数组需要有length属性
如果是数组,直接复制数组
demo:
let arr=[1,2,3,4,5]; console.log(Array.from(arr));//[1,2,3,4,5] let json={ 0:'zahngsan', 1:'lisi', 2:'wangwu' }; console.log(Array.from(json//[] let json={ 0:'zahngsan', 1:'lisi', 2:'wangwu', length:3 }; console.log(Array.from(json//['zhangsan','lisi','wangwu']
let json={ 0:'zahngsan', 1:'lisi', 2:'wangwu', length:2 }; console.log(Array.from(json//['zhangsan','lisi']
Array.of() :把一组值转为数组
demo:
console.log(Array.of('1','2','3'));//[1,2,3]
arr.find() 找到第一个符合条件的数组成员,如果没有返回undefined
demo:
let arr=[1,2,3,4,5]; let bb=arr.find((item,index,arr)=>{ return item>3; }); console.log(bb);//4
function demo(){ let arr=[1,2,3,4,5]; let bb=arr.find((item,index,arr)=>{ return item>5; }); console.log(bb);//undefined }
arr.findIndex() : 找到第一个符合条件的数组成员的索引,如果没有返回-1
function demo1(){ let arr=[1,2,3,4,5]; let bb=arr.findIndex((item,index,arr)=>{ return item>5; }); console.log(bb);//-1 } function demo2(){ let arr=[1,2,3,4,5]; let bb=arr.findIndex((item,index,arr)=>{ return item>3; }); console.log(bb);//3 }
arr.fill(填充的内容,开始位置,结束位置) 填充数组规定位置的数据
function demo(){ let arr=[1,2,3,4,5]; let bb=arr.fill('x',0,2); console.log(bb);//['x','x',3,4,5] }
arr.includes()
对象
对象的简洁语法
let name='zhangsan'; let age=20; let json={ name,//name:name age//age:age }
Object.is(值1,值2);比较两个值是否相等
console.log(NaN==NaN);//false
Object.is(NaN,NaN);//true
console.log(N0==-0);//true
Object.is(0,-0);//false
Object.assign(目标对象,source1,source2,...source3) ///合并对象,后面的值覆盖前面的值
作用: 就复制一维对象 合并参数
Object.assign([],[2,3,4,5])//[2,3,4,5] Object.assign({},{name:'zhangsan'})//{name:'zhangsan'}
Object.keys() Object.values() Object.entries()
demo:
let {keys,values,entries}=Object;//解构赋值 let json={name:'zhangsan',age:20}; for(let key in keys(json))console.log(key)//name age 等价于: for(let key in Object.keys(json))console.log(key)//name age for(let value in values(json))console.log(value)//'zhangsan' 20 等价于: for(let value in Object.values(json))console.log(value)//'zhangsan' 20
对象的解构赋值...
Promise
作用: 解决异步回调问题
let a=10; var promise=new Promise(function(resolve,reject){ if(a==100){ resolve('成功'); }else{ reject('失败'); } }); promise.then(res=>{ console.log(res); }).catch(err=>{ console.log(err); });
Promise.resolve('aa')//将现有的东西转成一个promise对象,reslove状态,成功状态
Promise.reject('bb')//将现有的东西转成一个promise对象,reject状态,失败状态
let a=Promise.resolve('aaa'); 等价于: a=new Promise((resolve,reject)=>{ resolve('aaa'); }); a.then(res=>{ console.log(res); }) let b=Promise.reject('bbb'); 等价于: b=new Promise((resolve,reject)=>{ reject('bbb'); }); b.catch(res=>{ console.log(res); })
Promise.all([p1,p2,p3,...])//把promise打包,扔到一个数组里面,打包完之后还是一个Promise对象,必须确保,所有的promise对象,都是resolve状态,都是成功的状态,其中有一个不是就会报错,走的是reject
demo:
let a=Promise.resolve('aaa'); let b=Promise.resolve('bbb'); let c=Promise.resolve('ccc'); Promise.all([a,b,c]).then(res=>{ console.log(res);//['aaa','bbb','ccc'] }).catch(err=>{ console.log(err); }); let a1=Promise.resolve('aaa'); let b1=Promise.resolve('bbb'); let c1=Promise.resolve('ccc'); Promise.all([a1,b1,c1]).then(res=>{ console.log(res); }).catch(err=>{ console.log(err);//bbb });
Promise.race([p1,p2,p3,...])//跟Promise.all()的区别:一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
模块化:
commonjs 主要服务端: nodeJS
AMD requireJs curJs
CMD seaJs
1 如何定义模块
2 如何使用模块
使用模块:
<script type='module'></script>
导出模块: export
导入模块:import 路径可以是相对路径也可以是绝对路径,无论导入多少次,只会被导入一次
import '文件路径'//相当于导入一个文件
demo:
1.js const a=1; const b=2; const c=3; export{a,b,c} 2.js使用 import {a,b,c} from '1.js' console.log(a,b,c);// 1 2 3 //名字要一致 变量名可以重命名 1.js const a=1; const b=2; const c=3; export{a as aaa,b as bbb,c as ccc} 2.js使用 import {aaa as a ,bbb as b,ccc as c} from '1.js' console.log(a,b,c);// 1 2 3 3.js使用 import {aaa ,bbb,ccc} from '1.js' console.log(aaa,bbb,ccc);// 1 2 3
导入所有导出的数据
import * as demo from '1.js
1.js const a=1; const b=2; const c=3; export{a,b,c} 2.js import * as demo from '1.js' console.log(demo.a,demo.b,demo.c);//1 2 3
export default 导出的数据,导入的时候不需要{}
1.js export default a=10; 2.js import a from '1.js' console.log(a)//10 1.js export default a=10; export const b=20; 2.js import a {b} from '1.js' console.log(a,b)//10 20
import 有提升效果,import会自动提升到顶部,首先执行
导出到模块的内容,如果里面有定时器更换,外面也会改动,不同commonJS的缓存
import() 类似node里面的require,可以动态引入,默认import语法不能写在if之类里面;
import() 可以写在if语句中,可以使用动态路径;路径可以是相对的或者是绝对的;按需加载;返回的是Promise对象可以使用then
demo:
1.js export const a=10; export const b=20; 2.js import('1.js').then(res=>{ console.log(res.a,res.b);、、10 20 });
结合promise使用
demo:
1.js export const a=10; 2.js export cosnt b=20; 3.js Promise.all([import('1.js'),import('2.js')]).then((mode1,mode2)=>{ console.log(mode1,mode2);//{a:10} {b:20} );
类
class Person{
constructor(){ //构造函数(方法),调用new,自动执行
}
}
demo:
class Person{ constructor(name,age){ console.log(`构造函数执行了name:${name},年龄:${age}`); } } new Person('zhangsan',18);//构造函数执行了name:zhangsan,年龄:18
es5 模拟类:
let Person=function(name,age){ this.name=name; this.age=age; } Person.prototype.showName=function(){ console.log(this.name); } Person.prototype.showAge=function(){ console.log(this.age); }
es6定义类:
class Person{ constructor(name,age){ this.name=name; this.age=age; console.log(`构造函数执行了name:${name},年龄:${age}`); } showName(){ console.log(`name:${this.name}`); } showAge(){ console.log(`age:${this.age}`); } } let p=new Person('zhangsan',18); console.log(p.showName(),p.showAge());
注意点:
1 constructor new时自动调用
2 方法之间没有逗号,间隔
3 方法不能加function关键字
类也可以使用变量命名方式
let Person=class{ constructor(name,age){ this.name=name; this.age=age; console.log(`构造函数执行了name:${name},年龄:${age}`); } showName(){ return `name:${this.name}`; } showAge(){ return `age:${this.age}`; } } let p=new Person('zhangsan',18); console.log(p.showName(),p.showAge());
方法可以使用变量名:
let a='showName'; let b='showAge'; class Person{ constructor(name,age){ this.name=name; this.age=age; console.log(`构造函数执行了name:${name},年龄:${age}`); } [a](){ return `name:${this.name}`; } [b](){ return `age:${this.age}`; } } let p=new Person('zhangsan',18); console.log(p.showName(),p.showAge()); console.log(p[a](),p[b]());//与上面的等价
注意点:
es6里面的class没有提升功能,只能先定义再使用,再ES5中,用函数模拟,有提升功能,function本身有提升功能
矫正this:
1 fn.call(this指向谁,args1,args2...);
2 fn.apply(this指向谁,args1,args2,...);
3 fn.bind(this指向谁)
class里面取值(getter)存值(setter)封装框架会用到
静态方法:类身上的方法,直接使用类调用 static,子类可以继承父类的静态方法
demo:
class Person{ constructor(name,age){ this.name=name; this.age=age; } static aa(){ return 'this is aa' } showName(){ return `name:${this.name}`; } showAge(){ return `age:${this.age}`; } } let p=new Person('zhangsan',18); console.log(Person.aa());//this is aa,只能用类进行调用,不能用实例调用
类的继承
extends关键字实现
demo:
class Person{ constructor(name,age){ this.name=name; this.age=age; } static aa(){ return 'this is aa' } showName(){ console.log('这是父类的showName方法') return `name:${this.name}`; } showAge(){ return `age:${this.age}`; } } class Student extends Person{ constructor(name,age,skill){ super(name,age);//继承父类的属性name age this.skill=skill; } showName(){ super.showName();//继承父类的showName方法 console.log('这是子类的showName方法') } showSkill(){ return `技能${this.skill}` } } let stu=new Student('zhangsan',18,'学习'); console.log(stu.showSkill()); stu.showName();
1 子类定义自己的contructor需要使用super关键字继承父类的属性,然后可以添加自己的属性
2 字类可以定义与父类一样的名字的方法,直接覆盖父类的方法
3 子类继承父类的方法,并添加自己的方法,需要使用super关键字,先继承父类的方法,再写自己的私有方法,这样先执行父类的方法,再执行子类的方法
新增数据类型
number string object function undefined bollean
symbol
1 Symbol不能new
2 Symbol() 返回是一个唯一值,做一个key,定义一些唯一或者私有的东西
3 symbol是一个单独数据类型,就叫symbol基本类型
4 如果symbol作为key,用for in循环,出不来(因为是私有的,不显示)
generator函数
生成器
解决异步的问题,深度嵌套的问题,现在使用asyns
语法:
function * show(){} 在function和方法名之间有一个*号
yield
demo:
function * gen(){ yield "welcome"; yield "to"; return '牧马人' } let g1=gen(); 使用方法: 手动调用 g1.next();//{value:'welcome',done:false} g1.next();//{value:'to',done:false} g1.next();//{value:'牧马人',done:true} for...of 自动遍历generator for(let value of g1){ console.log(value);// welcome to }
return的东西不会遍历
也可以使用解构赋值
let [a,...b]=gen();//a:'welcome' b:to
console.log(...gen)//['welcome','to']
console.log(...gen)//['welcome','to']
generator一般配合promise使用
async和await
async特点:表示的就是异步,这个函数里面有异步任务
await 表示后面结果需要等待
async特点:
1 await只能放在async函数中
2 await后面可以是promise对象,也可以是数字 字符串
3 相比generator语义化更强
4 async返回的是一个promise对象
5 只要await语句后面Promise状态变成reject,那么整个async函数就会中断执行
async函数中抛出错误,影响后续代码:
1 使用try catch
try{}catch(err){}
2 promise本身就有catch,直接使用catch
demo:
async function demo(){ await Promise.reject('出错了') console.log(await Promise.resolve('success')) console.log(await Promise.resolve('success1')) } demo();
结果:
出错了,后面的代码不会执行;
使用try catch
async function demo(){ try{await Promise.reject('出错了')}catch(err){ console.log(err); } console.log(await Promise.resolve('success')) console.log(await Promise.resolve('success1')) } demo();
下面的代码依然执行
使用promise的catch
async function demo(){ await Promise.reject('出错了').catch(err=>{ console.log(err); }) console.log(await Promise.resolve('success')) console.log(await Promise.resolve('success1')) } demo();
结果同上
使用await的地方一般都是数据请求,都有出错的可能,都需要进行出错检测,建议都放在try catch中
async function demo(){ try{ await Promise.reject('出错了'); await Promise.resolve('success') await Promise.resolve('success1') }catch(err){ console.log(err); } } demo();
Set WeakSet
新增的数据结构
Set数据结构,类似数组,但是里面不能有重复值
set的用法:
new Set([]);参数是一个数组 存储的是一个数组
数组去重
let arr=[1,2,3,4,5,1]; let setArr=new Set(arr); console.log(setArr);
转成数组
Array.from(setArr)
let arr2=[...setArr]
set添加值 add
let setArr=new Set();
setArr.add('a');
setArr.add('b');
setArr.add('c');
删除一项元素
setArr.delete('a')
判断set中是否包含某个值
setArr.has('a')//返回true false
setArr.size 属性,查看个数
setArr.clear()清除所有
可以使用for of进行遍历取值
setArr没有下标
WeakSet({}) 存储的是一个json,初始添加json不行,没有size和clear()需要用add添加 不太靠谱
总结:new Set() 不适用weakSet()
map
map:类似json,但是json的键(key)只能是字符串
map的key可以是任意类型
用法:
设置值set
取值 get
删除元素 delete
是否包含某个元素has(key)
清空clear()
循环:
for of
demo:
let map=new Map(); let json={a:1,b:2}; map.set('a','aaa'); map.set(json,'aaa'); map.set('aaa',json); console.log(map); console.log(map.get(json));
WeakMap() 官方文档说的是:key只能是对象
总结:
Set 里面是数组,不重复,没有key,没有get方法
Map 对json功能的增强,key可以是任意类型的值
Number
Number.isNaN()判断是否是NaN
Number.parseInt
Number.parseFloat
新增的方法
Number.isFinite()判断是否是数字
Number.isInteger() 判断数字是否是整数
安全整数:
-(2^53-1)~(2^53-1)
Number.isSafeInteger() 判断是否是安全整数
Number.MAX_SAFE_INTEGER 最大安全整数
Number._MIN_SAFE_INTEGER 最小安全整数
Math
Math.abs()
Math.sqrt()
Math.sin()
Math.cos()
Math.trunc() 截取数据的整数部分
Math.sign(0) 0 Math.sign(-0) -0 Math.sign(3) 1 Math.sign(-3) -1 其他值 NaN
Math.cbert() 取一个值得立方值
Math.cbert(27) 3
判断一个数是 正数 负数 0 -0