ES6
-
var声明的变量有变量提升,let没有
-
let有块级作用域,var没有
-
const用于声明常量,声明时赋值,对于基本数据类型,变量声明了不能重新赋值。对于引用数据类型,引用地址指针不能改变,但是地址中的内容可以改变。
-
在for循环中不适合使用var定义变量
(1).for循环是同步的,内部事件处理函数是异步的,所以等到异步事件触发的时候,同步代码已经跑完,因此i也加完了(这就是为什么i固定为最大值不变的原因)。
(2).处理的核心思想就是在他跑完前就立即记录i的值,以备异步事件处理函数使用。
(3).说白了就是利用var只有函数作用域,制造独立空间,让每个i都是独立的。
for (var i = 0; i < 10; i++) { setTimeout(function(){ console.log(i); }) }// 输出十个 10 for (let j = 0; j < 10; j++) { setTimeout(function(){ console.log(j); }) }// 输出 0123456789
-
模板字符串,使用反引号(tab键上方的键)包裹字符串,中间可以存在回车,字符串中存在的变量可以使用${变量}的方式进行占位。
旧版本中定义字符串时要进行拼接: let pid = 1; let name = linux; let a = "<ul><li><p id = "+ pid + ">" + name "</p></li></ul>" //拼接麻烦 let pid = 2; let name = linux; let b = `<ul> <li> <p id = ${pid} > ${name} </p> </li> </ul>` //模板字符串保留了原有的html结构,其中的变量通过占位符替换
-
函数参数带默认值
function add(a = 10 , b = 20){ //调用add函数未传递值时,默认a = 10 , b = 20 return a + b ; } add();//return 30; add(1 , 2);//return 3; function addes5(a, b){//es5的做法 a = a || 10; //调用add函数,进行判断是否传值,未传递时,给a = 10 , b = 20 b = b || 20; return a + b ; }
-
剩余参数,使用三个点+紧跟着的具名变量表示,作为函数形参,必须作为最后一个参数。
function add(a , b , c , ...nums){//nums是剩余参数,nums会自动转换为一个数组 } add(1,2,3,4,5,3,4,6)//4,5,3,4,6转为数组存放在nums中
-
扩展运算符,同样是三个点加一个数组变量表示,表示将一个数组的每一个元素都分解开,作为独立的参数传给一个函数。
let nums = [1,2,3,4,34] console.log(Math.max(...nums))//输出 : 34 es5中如果要取出nums中的最大值,采用的方式是: console.log(Math.max.apply(null,nums))//输出 : 34
-
arguments
对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments
对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引 0 处。 arguments是“类数组” ,即arguments
有长度
属性 并且属性的索引是从零开始的,但是它没有 Array的 内置方法, 例如forEach()
和map()
都是没有的 -
箭头函数: 通过 ()=>{} 来定义函数 , 等价于 function(){} , 当参数个数只有1个时有更加简便的写法:
//有两个以上的参数: let add = (a , b) => { return a + b; } add(1,2) ; //return 3; //一个参数: let get = val => { //code return ; } //一个参数,且函数中可以直接写return返回表达式时可以简写: let get1 = val => (val + 2); //一个参数,且直接返回输入的参数时: let get2 = val => val;//表示get2(val)函数直接返回val; //多个参数,直接返回表达式: let add1 = (a,b)=> (a+b); //没有参数时,表示参数的小括号不能省略 let getStr = () = > 'hello world!' + 123; console.log(getStr()) //返回值为对象时,返回的对象必须使用小括号包裹: let getObj = () => ({id : 1 , name: 'linux'})
-
箭头函数没有this指向,箭头函数内部的this指向只能通过查找作用域链来决定,(所以定义函数时,为了this能正确的指向,function定义和=> 定义的方式要合理的使用)
let pageHandle = { id : 1, init: function(){ // 此处如果使用箭头函数,那会导致内部的this直接指向Window document.addEventListener("click",(event)=>{ this.doSomeThings(event.type);//这里的this指向,先查找到上一级的function,在通过function中的this指向,指向pageHandle,这样才能调用到doSomeThings()方法。 },false) }, doSomeThings:(val)=>val } ///------------------- let pageHandle = { id : 1, init: function(){ document.addEventListener("click",function(event){ this.doSomeThings(event.type);//这里的this直接指向了document,document中不存在doSomeThings()函数,会导致报错。 },false) }, doSomeThings:(val)=>val }
-
箭头函数使用注意事项:
(1)箭头函数中没有arguments对象
(2)箭头函数不能使用new关键字创建对象,(可以认为 function定义的函数就是一个对象结构,可以使用new创建对象,但是()=>{}不被认为是一种对象结构)
-
解构赋值:对赋值运算的扩展使用,针对对象和数组来操作,使得代码简洁;
let person = { id : 1, name: "foo", age: 20 } //现在有name , age两个变量,需要分别拿到person中name和age的值, //原来的写法是: let name = person.name; let age = person.age; //es6中的写法: let {name , age} = person//这样就定义好了name和age并且分别拿到了person中的对应数据。
-
比较两个值是否严格相等: 使用===或者对象方法is(),
===和Object.is()方法的不同点在于: console.log(NAN === NAN) // false; Object.is(NAN,NAN) // true
-
对象中assign(targetObj , …obj)方法,有多个参数,作用是从第二个开始的对象全都合并到第一个对象中,并且返回值为一个新的合并之后的对象。
let person = {} let newPerson = Object.assign( person , {id : 1} , { name : "linux"} , {age : 24}) //peron 和newPerson是内容一样的两个对象 , 内容都是 {id : 1 , name : "linux" , age : 21}
-
新增的原始数据类型:Symbol类型 , 用于表示一个独一无二的值,一般在声明对象的室友属性时使用 , 使用的比较少
const id = Symbol("id") console.log(id) //输出: Symbol(id) let person = {} person[id] = 1 console.log(person[id])// 输出: 1 , 注意获取该独一无二的id属性时,必须通过对象[]的方式,不能使用对象.属性的方式 console.log(person.id)//报错.....
-
Set集合对象 : 无重复值的 、 无类型规定的、有序的数据集合类型,(注意: set中的引用对象无法被释放)
let dataSet = new Set() //添加数据使用add() dataSet.add(2); dataSet.add("linux"); dataSet.add(false); dataSet.add([1,2,3,4]); //删除元素使用delete() , 删除成功返回true,不存在要删除的数据时,删除失败返回false dataSet.delete(2); //判断元素是否已经存在,返回bool类型 dataSet.has("linux"); //set集合有size属性,可以获取该集合中数据个数 console.log(dataSet.size) // 注意 这里的size只是对象属性,不是对象方法
-
Map集合对象:key-value形式的有序集合,key和value可以是任意类型的值
let m = new Map() //添加元素: m.set("msg" , "dddddd") m.set(3,'dak') //获取某个key对应的vlaue: m.get("msg") //除此之外,map同样有has(),delete(),clear()等方法,也有size属性。
-
数组Array中的from()和of()方法:
//from():将伪数组转换成一个真正的数组,例如function中的arguments就是一个伪数组 let eg = function(a ,b,c){ let arr = Array.from(arguments) } //将伪数组转换为数组的还可以使用扩展运算符: let eg = function(a ,b,c){ let arr = [...arguments] } //from()方法还可以有一个回调函数作为第二个参数,在将伪数组转换遍历的过程中,去执行这个回调函数 //of():将传入的任意的数据类型和对象放到一个数组中 let arr = Array.of(2,"42",true,false , ["3s",32],{id:3,name:"linuc"}) console.log(arr)//输出为:[ 2, '42', true, false, [ '3s', 32 ], { id: 3, name: 'linuc' } ]
-
数组中的find()和findIndex()方法:
//两个方法都是接收一个回调函数作为参数,find用于查找出第一个符合条件的元素,findIndex用于查找出第一个符合条件的元素的索引 [1,2,3,5,0,32,78,4].find( n => (n>10) ) //返回 32 [1,2,3,5,0,32,78,4].find( n => (n>10) ) //返回 5
-
数组中的keys() ,values() , entries()方法:
//三个方法都是返回一个遍历器,通过遍历器就能使用for...of方式遍历数据 //Array.keys():返会数组中索引的遍历器 //Array.values():返会数组中元素的遍历器 //Array.entries():返会数组中[索引,元素]组成的数组的遍历器 for(let index of ["sa","cs","ds"].keys()){ console.log(index) }//输出: 0 1 2 for(let val of ["sa","cs","ds"].keys()){ console.log(val) }//输出:sa cs ds for(let [index,val] of ["sa","cs","ds"].entries()){ console.log(index); console.log(val); }//输出:0 sa 1 cs 2ds
-
生成器(generator): generator函数是分段执行的,yield是暂停程序执行,next是恢复执行,可以用于实现程序的异步操作
//生成器是 定义是带有*的函数func(),该函数被调用时返回一个迭代器,生成器函数内部使用yield关键字可以让程序挂起,并返回yield关键字修饰的内容; function *func(){ console.log("1") yield 5; console.log("2") yield 6; console.log("3") yield 7; console.log("4") } let ite = func() // 返回一个迭代器 //使用迭代器中的next()方法让程序一步步执行,并将yield 修饰的内容转换为一个特定的对象后返回 let a = ite.next() // 第一次执行函数,控制台打印 1 ,在yield 5处停止执行,并将5封装成一个对象返回给a console.log(a) // 输出 : {value : 5 , done : false} ,done为false:表示程序还没有执行完成 let b = ite.next() // 第二次执行函数,控制台打印 2 ,在yield 6处停止执行,并将6封装成一个对象返回给b console.log(b) // 输出 : {value : 6 , done : false} ,done为false:表示程序还没有执行完成 let c = ite.next() // 第三次执行函数,控制台打印 3 ,在yield 7处停止执行,并将7封装成一个对象返回给c console.log(c) // 输出 : {value : 7 , done : false} ,done为false:表示程序还没有执行完成 let d = ite.next() // 第三次执行函数,控制台打印 4 ,由于后面没有了yield 修饰的内容了,所以直接将undefined封装成一个对象返回给d console.log(d) // 输出 :{value : undefined , done : true}
-
Promise对象:处理异步操作的三个状态 进行中(pending) 、 成功(resolved)、失败(rejected),状态的改变只能是从进行到成功或者到失败,两种,状态一旦发生改变,就不能再改变
//Promise对象 //Promise对象中接收两个函数作为参数,第一个表示成功完成状态的函数,第二个表示失败状态的函数 let pro = new Promise((succeed,rejected)=> { //异步代码 ,请求逻辑代码 let resData = {//模拟一个请求返回的 code : 201, data: { id : 10, name : "linuc", age : 10 } } setTimeout(()=>{//模拟一个异步请求 if(resData.code === 200){ succeed(resData.data)//通过第一个参数函数返回数据 }else{ rejected("请求失败")//通过失败参数返回数据 } },1000) }) //then()方法可以接收一个或者两个函数参数,第二个参数可选 pro.then((sucData)=>{ console.log(sucData)//输出的就是succeed()函数中返回的数据 },(regData)=>{ console.log(regData)//输出的是rejected()函数中返回的数据 }) //catch()方法,用于捕获异步请求失败的返回信息 //pro.then(null,(rejData)=>{})等价于pro.catch(()=>{}) //通过使用如下格式 pro.then((sucdata)=>{ }).catch((rejData)=>{ })
-
Promise对象中的resolve()、reject() 、all()、race()方法
resolve(参数)
可以将任何对象转换成一个成功状态的Promise对象,resolve(参数)中的参数就是转换后Promise对象返回的成功状态数据;
reject(参数)
同理,可以将任何对象转换成为一个失败装填的Promise对象,传入的参数及时转换后Promise对象返回的失败装填数据;
let proms = Promise.resolve("成功") let promr = Promise.reject("失败") proms.then((data)=>{ console.log(data);//输出:成功 }) promr.catch((data)=>{ console.log(data);//输出: 失败 })
all(一个存储了多个Promise对象的数组作为参数)
参数为一个数组,数组中存放了多个Promise对象,all()方法返回一个新的Promise对象,当且仅当数组中所有的Promise对象都处于成功状态(resolved)时,返回的新Promise才处于成功状态,否则新对象处于失败状态(rejected)。新的Promise对象,如果成功,成功状态数据是一个数组,该数组中存放了原来的每个Promise对象返回的成功数据;如果失败,只会存放一个失败的Promise对象的数据,如果有多个Promise对象失败,也只会存放其中一个数据
应用:多请求,大量数据加载时,为了保证请求都成功之后才进行后续操作(如页面渲染),每一个请求都放在一个Promise中,最后用all()方法保证数据请求成功
//-------------全成功情况 let proms1 = Promise.resolve("成功1") let proms2 = Promise.resolve("成功2") let proms3 = Promise.resolve("成功3") let promAll = Promise.all([proms1,proms2,proms3]) promAll.then((data)=>{ console.log(data)//输出:['成功1', '成功2', '成功3'] }).catch((data)=>{ console.log(data); }) //--------------有失败情况 let proms4 = Promise.resolve("成功4") let proms5 = Promise.reject("失败5") let proms6 = Promise.reject("失败6") let promAll1 = Promise.all([proms4,proms5,proms6]) promAll1.then((data)=>{ console.log(data) }).catch((data)=>{ console.log(data);//输出: 失败5 })
race(一个存储了多个Promise对象的数组作为参数)
该方法有竞速的意思,多个Promise对象同时进行,当某一个Promise的状态率先从进行中(pending)转变了其他状态(不管是成功还是失败),那么race()方法返回一个Promise对象,该Promise的状态和率先完成状态转换的那个Promise对象的状态一致,并且返回的数据也一致。
总结: 谁第一个成功或失败,就认为是race的成功或失败。
应用: 请求超时提示,其中一个Promise对象中设置超时时间,当达到一定的时间后,触发该Promise对象状态转换,其他的Promise对象正常执行其他操作(异步请求)
let prom = new Promise((suc,rej)=>{ //异步操作 suc("成功1") //rej("2222") }) let prom1 = new Promise((suc,rej)=>{ //异步操作 //suc("成功2") rej("222222") }) let pror = new Promise((suc,rej)=>{ setTimeout(()=>rej("超时2222"),3000)//设置3秒后该Promise对象状态变为失败 }) let pro = Promise.race([prom,prom1,pror])//三个Promise对象竞速,其中最后一个Promise一定会在3秒后执行成功 pro.then(data=>{ console.log(data) }).catch(data=>{ console.log(data) })
-
async和await
async
:作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样 , 该函数一定会返回一个Promise对象,如果return后面不是一个Promise对象,会自动将return的内容封装成一个已经正常执行的Promise对象。async function get(){ return "aaa" } console.logg(get())//一个内容为aaa的Promise对象
await
:只能在async关键标识的函数内使用,用于等待一条语句的执行完成(一般用来等待Promise对象的执行完成),某些语句(如请求资源较大)执行时间较长,后续的语句必须在该语句完成之后才能继续执行。当语句不是Promise对象执行语句,那么await 标识的语句与正常不标识的语句是一样的正常执行;当语句还是Promise对象语句时,如果该Promise成功执行,那么程序正常进行,如果Promise失败,那么程序会直接终止,不执行后面的语句(因为后面的语句是等待await语句执行成功才能执行的)async function get(){ let pror = await new Promise((suc,rej)=>{ setTimeout(()=>suc("正常2222"),3000) }) console.log(pror);//正常输出一个Promise对象 let pror1 = await new Promise((suc,rej)=>{ setTimeout(()=>rej("超3333"),3000)//失败,直接跳到return,返回错误内容为:超时3333 }) console.log(pror1);//该语句未执行 return pror1 } console.log(get())//因为上面的函数是一个异步函数,所以整条语句最先输出,输出一个内容 undefined 的Promise对象
-
类和对象
基本与java中一样,使用class关键字声明一个类,类名首字母大写,构造方法的命名规定为constructor()
class Person{ constructor(name){//构造方法 this.name = name // 属性可以不用额外进行声明,构造方法里有this.name,这个name就会变为这个类的一个属性 } getName(){ retrun this.name; } }
类的继承同样是采用extends关键字,基本使用和JAVA一样
class Student extends Person{ constructor(name , age){ super(name) this.age = age } //重写getName()方法 getName(){ return `student name is ${name}` } }
对象创建也是是使用new 关键字
const student = new Student("linux",12)
-
模块化module (就是通过export和import关键字实现文件之间的相互引用)
js中一个文件就是一个模块
export
关键字:用于在js文件中说明该文件中的一些对外接口,一个文件中可以有多个export const name = 'linux' export const person ={ name: "linuy", age: 10 } export function fuc(){ console.log("方法") }
export default
关键字:用于说明该文件的一个默认对外接口,一个文件中只能有一个export default let author = 'linuy'
通过{}结构批量的说明对外接口:
const name = 'linux' const person ={ name: "linuy", age: 10 } function fuc(){ console.log("方法") } export default let author = 'linuy' export { name,person,fuc }
import
关键字:引入其他文件暴露(export)的接口注意前提:
1.将需要使用其他模块的文件声明为一个模块(在script标签上添加 type = “module” 属性即可)
2.相互引用的文件要在一个服务器或者互通的服务器中,即两个静态文件是不能相互引用的
<script type = "module"> import author , {name , age , fuc} from "文件地址" </script>
* as
全部导入:将某个模块暴露的接口全部导入import * as all from "文件地址" //all 这个名字可以随意命名 //这样导入的就是整个模块module