1.变量相关操作
let声明变量 const声明常量--声明变量,常量的扩展
let不允许重复声明,var可以。
const不允许重复声明,一旦声明不可修改,声明常量必须赋值,不能和var一样声明后再定义。
块级作用域--es6中定义的变量是块级作用域
es5中的变量是函数级作用域。
es6中凡是{}包裹的代码都是块级作用域,凡是在块级作用域中用let声明的的变量和const声明的的常量都有一个暂时性死区,作用域只能在{}内。
解构赋值--对赋值运算符的扩展
针对数组或者对象进行模式匹配,然后对其中的变量进行赋值
/* *1.赋值两边的结构必须完全一样 *2.赋值的右边必须是个标准对象 *3.赋值和解构必须在同一个语句中完成 */ let {a,b}={'a':1,'b':2}; console.log(a) let {c,d}=[3,4]; console.log(c)
2.函数
箭头函数
表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super
function add(x){ return x+1; } function tip(y,fn){ console.log(fn(y)) } //es5 tip(1,add) /*
*es6 *如果有且有一个参数,()可以不写 *如果有且仅有一个语句并且是return,{}也可以不写 */ tip(5,(x)=>{return x+1}) tip(5,x=>x+1)
修正this
箭头函数this为父作用域的this,不是调用时的this
<button id='btn'>按钮</button> let btn=document.getElementById('btn'); btn.onclick=function(){ //es5 window.setTimeout(function(){ console.log(this.id) //undefined },2000) //es6 window.setTimeout(()=>{ console.log(this.id) //'btn' },2000) }
剩余参数--参数以...为前缀
允许将一个不定数量的参数表示为一个数组,它不仅可以收集,还能解构数据
function tip(x,y,...z){ console.log(z) } tip(1,2,3) //[3] tip(1,2,3,4,5) //[3,4,5] tip(1) //[]
3.数组扩展方法
map方法--使用场景(假设后台返回的数据是一个数组对象,前端可以使用map返回一个新的数组)
当数组调用map方法时,即将原有的数组内容变换成新的数组内容
/*
*val表示元素值
*idx表示元素索引号 *arr表示遍历的数组 *函数必须要有return语句,没有return就没有新的数组 */ let array=[30,40,50,60,70] let arr2=array.map(function(val,idx,arr){
return (val>=60?'及格':'不及格')
})
console.log(arr2)
forEach方法
该方法用于数组中各元素的遍历,可以对遍历时的元素进行各项操作,但不会返回新的数组
/* *val表示元素值 *idx表示元素索引号 *arr表示遍历的数组 *无返回值的函数,不会有新的数组产生 */
<button>1</button><button>2</button><button>3</button>
let arr=[30,40,50,60,70]
let btns=document.getElementByTagName('button');
let _btns=Array.from(btns) //将类数组转化为真正的数组--Array.from()
arr.forEach(val=>{console.log(val++)})
_btns.forEach(val=>{console.log(val)})
reduce方法
该方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
/* *initv-pro添加前初始值,若填,idx从0开始,若不填idx从1开始 *val表示元素值 *idx表示元素索引号 *arr表示遍历的数组 *函数必须要有return语句,没有return就没有新的数组 */ let arr=[30,40,50,60,70] let arr2=arr.map(function(pre,val,idx,arr){ if(idx===arr.length-1){ return (pre+val)/arr.length //求平均值 }else{ return pre+val //求和 } },10)
console.log(arr2)
filter方法
该方法用于数组中各元素的过滤,如果返回值为true,则作为新数组成员,否则被过滤
/* *原数组不变,返回新的数组arr2 *val表示元素值 *idx表示元素索引号 *arr表示遍历的数组 *函数必须要有return语句,没有return就没有新的数组 */ let arr=[30,null,undefined,'',0,40,50,60,70]; let arr0=arr.filter(val=>val) //不为真的内容 let arr2=arr0.filter(val=>val%2===0) //偶数
console.log(arr0)
console.log(arr2)
4.字符串对象扩展方法
查询子类字符串的方法--es5里面使用indexOf()
string.includes(cStr,pos); //在字符串中查找
string.startsWith(cStr,pos); //在字符串开始位置查找
string.endsWith(cStr,pos); //在字符串结束位置查找
let str='this is a book'; //cStr:表示要查找的子字符串,pos:表示查询时的开始位置,不传默认为0 string.includes(cStr,pos); //在字符串中查找 str.includes('is') //true str.includes('is',6) //false str.includes('is',5) //true //cStr:表示要查找的子字符串,pos:表示查询时的开始位置,不传默认为0 string.startsWith(cStr,pos); //在字符串开始位置查找 str.startsWith('ab') //false str.startsWith('th') //true str.startsWith('th',2) //false //cStr:表示要查找的子字符串,pos:表示针对前第几个字符 string.endsWith(cStr,pos); //在字符串结束位置查找 str.endsWith('ok') //true str.endsWith('th') //false str.endsWith('ok',2) //false str.endsWith('th',2) //true
字符串重复与补全的方法
string.repeat(count) //重复显示指定的次数
string.padStart(lMax,aStr) //字符串的补全--左侧
string.padEnd(lMax,aStr) //字符串的补全--右侧
let str='hi,';
//count表示需要重复的次数,若为小数,向下取整 string.repeat(count); //字符串重复显示指定的次数 str.repeat(2); //'hi,hi' str.repeat(3.7); //'hi,hi,hi,' //lMax:表示字符串最大的字符长度,aStr:表示需要补充的字符串内容 string.padStart(lMax,aStr); //给字符串进行补全操作--左侧
let str2='1';
str2.padStart(2,'0'); //'01'---小于10的时候字符串补全
str.padStart(6,'hi,'); //hi,hi, //lMax:表示字符串最大的字符长度,aStr:表示需要补充的字符串内容 string.padEnd(lMax,aStr); //给字符串进行补全操作--右侧 str.padEnd(6,'Tom'); //hi,Tom str.padEnd(8,'Tom'); //hi,TomTo
字符串模版
它是一个加强版的字符串,用反引号`进行包裹,
1.换行和绑定变量,
2.调用函数,
3.执行表达式运算,
4.直接输入字符串内容
<body> <ul> <li>您好</li> </ul> <script> let name='Mike'; let x=8,y=9; function _name(item){ return item; } let str=`<ul> <li>${name},您好</li> <li>${_name('Tom')},您好</li> <li>结果:${'我是结果'}</li> <li>结果:${x>y?x:y}</li> </ul>`; let div=document.createElement('div'); div.innerHTML=str; document.body.appendChild(div); </script> </body>
5.类型扩展
symbol类型
它是es6中扩展的原始类型,表示唯一的值,没有结构函数,不能使用new关键字定义,用于确保对象中属性名的唯一性
//symbol类型 let name=Symbol(); let person={}; { person[name]='a1'; console.log(person[name]) //a1 } { let name=Symbol(); person[name]='b1'; console.log(person[name]) //b1 } console.log(person[name]) //a1 //string类型 let name='a'; let person2={}; { person2[name]='a1'; console.log(person2[name]) //a1 } { let name='a'; person2[name]='b1'; console.log(person2[name]) //b1 } console.log(person2[name]) //b1
Set集合类型---常常用于处理数组
es5中对象类型:函数,数组,简单对象。
es6新增对象类型:Set类型,Map类型。
set集合类型:该类型的对象是一个集合,允许存储任何类型的值,但保存的值必须唯一,可以增加,删除和检测集合中是否包含指定属性名。
1 let arr=[1,3,5]; 2 let arr2=[2,4,6,5]; 3 4 let a1=new Set(); 5 let a2=new Set(arr); 6 let a3=new Set(arr2); 7 8 a1.add("a":1,"b":2,"a":3); // 确保唯一性,后面的替换前面的 9 a1.add("abs"); 10 11 a2.add([2,3,4,5,6]); //add添加 12 a2.delete(3); //delete删除 13 a2.has(5) //has查找。存在为true,不存在为false 14 15 let c=new Set([...arr,...arr2]) 16 let d=new Set([...arr].filter(x=>a3.has(x))) 17 18 console.log(a1); 19 console.log(a2.size); //获取a2的长度 20 console.log(c) //数组除重 21 console.log(d) //获取交集元素
Map数据类型---常常用于处理对象
es5中对象的key必须为字符串,Map数据类型对其扩展,集合的键名和值支持任意类型的数据
Map数据类型:用于定义一个有序列表,表现也是一个集合,拥有增加,删除和查询的功能
/* *集合的键名和值支持任意类型的数据 *.set()方法存数据,.get()方法取数据,.delete()方法删除,.has()判断是否存在,.clear()清除整个集合 */ let m=new Map(); let n={}; m.set('a',1).set('c',2); m.set(n,1); let a1=m.get('c'); let a2=m.get(n); let f=m.has(n); //查找,是否存在某key,存在为true let d=m.delete('c') //删除操作 m.clear(); //清除整个集合中所有的键值对 console.log(a1) //2 console.log(a2) //1 console.log(m.size) //3 console.log(d) //true
iterator迭代器
为各种不同类型的数据访问提供了一种同意的接口,只要部署了它,各种数据类型就可以直接遍历各个成员。
/* *forEach语句里面不能用break跳出循环 *for in 效率不高,set,map定义的不能遍历 *for of存在内置遍历器,底层存在iterator迭代器的支持 *数组,类似数组,set集合对象,map集合对象 自动具有iterator迭代器 */ let arr=[2,4,6,8]; let obj={ length:2, 0:1, 1:2 } //Array.from将类数组转化为数组 for(let item of Array.from(obj)){ console.log(item) } for(let item of arr){ if(item==4){ break; }else{ console.log(item) } } for(let i of s){ console.log(i) }
6.处理异步嵌套调用
generator函数
为解决异步编程时的嵌套提供方案,函数返回一个生成器,根据yield语句生成每次挂起时的迭代器
/* *function后面跟*为generator生成器函数 *只要生成器里面通过yield给他声明,挂起的内容,可直接通过for of来直接获取 */ //定义 function * tip(){ yield '1'; yield '2'; yield '3'; } let gen=tip() //取值过程 for(let i of gen){ console.log(i) //1 2 3 undefined } let [a,...b]=gen; console.log(a,b) //1 [2,3] console.log(...gen) //1 2 3 //应用 function * ask(){ let id=yield '1010'; let work=yield id+'=>职业'; let ad=yield=work+'=>广告'; } let gen2=ask(); let id=gen2.next(); console.log(id.value); //1010 let work=gen2.next(id.value); console.log(work.value); //1010=>职业 let ad=gen2.next(work.value); console.log(ad.value) //1010=>职业=>广告
promise对象
为解决异步编程时的嵌套提供方案,该对象接收两个函数为参数,并将每次执行结果作为参数传给函数
//基本定义 let a=5; let p1=new Promise(function(resolve,reject){ if(a>3){ resolve(a) }else{ reject('error') } }) let p2=Promise.resolve('1010'); //使用 p1.then(function(s){ console.log(s) },function(e){ console.log(e) }) p2.then(function(d){ console.log('id',d); //通过id获取到用户信息 let user='用户信息'; return d+'=>'+user; }).then(function(d2){ console.log('user2',d2); //通过用户信息获取到爱好 let like='用户爱好' return d2+'=>'+like; }).then(function(d3){ console.log('like',d3); //通过用户信息获取到爱好 let ad='用户广告' return d3+'=>'+ad; }).then(function(d4){ console.log('ad',d4) })
async和await
async使用函数返回一个promise对象
await可以等待执行完成,使用异步请求变成同步效果
/* *async返回一个promise对象 *若await后面为一个普通的字符串,与普通函数没区别, *若await后面有promise对象并且里面有异步请求的功能 await等待执行完才执行下面语句 *若await作为一个返回值,则返回值的内容为异步请求成功之后的值传过来的内容 */ function p(str) { return new Promise((resolve)=>{ setTimeout(()=>{ console.log(str); resolve(str); },1000) }) } async function tip() { p('abc'); console.log('ok') } async function tip2() { let aa=await p('abc'); //等待 console.log(aa) console.log('ok') } tip() //'ok' 'abc' tip2() //'abc' 'abc' 'ok'
7.面向对象编程
es5里面没有类
类的定义
类的本质还是一个函数,class关键字是一个语法糖,使结构更清晰,形式上更似面向对象编程
/* * 不允许定义2个及以上一样的类 */ //声明一个类 class Person{ //类里面包括属性和方法2个成员 name='张三'; //原型属性 static sex='男' //静态属性,不需要实例话 say(){ //原型方法,不能获取静态属性,其他属性均可获取 console.log(this.name+','+this.age) } static play(a,b){ //静态方法,只能获取静态属性,其他均不可获取 console.log(a+b); console.log(this.age); //undefined console.log(this.sex); //男 } constructor(name,age){ //构造方法--实例话类对象的时候执行(new的时候)) this.name=name; this.age=age; console.log(this.name,this.age) } } Person.prototype.age=18; //公用属性 //定义一个类 let Person2=class{} //调用类 let p1=new Person('王麻子',28); console.log(p1.name,p1.age,Person.sex); p1.say(); Person.play(5,8)
类的封装和继承
封装使用类的成员更具统一性,继承可以扩展各类之间的联系,增加封装内容的复用性,可维护性。
/* * 不允许定义2个及以上一样的类 * 如果继承的子类函数,有一个constructor,则必须调用super,并且如果是一些动态的属性,必须在super函数里面直接引用过来,则可以在子函数中直接使用父级属性 * 调用父类静态方法,可在子类中自己定义一个静态方法,通过super对象访问里面的静态方法 * super若在静态方法中表示整个类的对象,若在constructor中则表示实例话对象 */ //声明一个类 class Person{ //定义属性 constructor(name,sex){ this.name=name; this.sex=sex; this.age=18; } //方法 say(){ console.log(this.name+','+this.sex+','+this.age) } static sing(){ console.log('唱歌中') } } //实例话一个类对象 let p1=new Person('王麻子','男'); //调用方法 p1.say(); //声明一个类 class Hero extends Person{ feature='勇敢'; constructor(name,sex,act){ super(name,sex,act); //继承Person里面所有属性 this.act=act; } play(){ console.log(this.act) } static sing2(){ super.sing(); } } //实例话Hero let h1=new Hero('张三','男','利落'); h1.say(); h1.play(); Hero.sing2() //Hero里面静态方法调用
模块化编程
es6中的模块化解决es5中不统一的问题,自动开启严格的结构模式,通股票import和export实现模块间的依赖关系
//common.html let name='张三'; let age=18; const PI=3.1415926; function add(a,b){ return a+b; } class Person{ constructor(name,sex){ this.name=name; this.sex=sex; } say(){ console.log(this.name+','+this.sex) } } export { name as n, age, PI, add, Person }; let num1=100; let num2=200; export default {num1,num2};
//mod.html <Script type='module'> //方法一引用 import num1,num2,{n,age as a,PI,add,Person} from './common.html' console.log(n,a,PI); console.log(add(5,8)); let p1=new Person('张三','女'); p1.say(); console.log(num1,num2) //方法二引用 import('./common.html').then(d=>{ console.log(d.n); let p2=new d.Person('王麻子','女'); p2.say(); }) </Script>