1.ES6的新特性
1.let声明变量
1.1let声明的变量由严格的局部作用域
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> //var 声明的变量会越域 // let 声明的变量由严格的局部作用域 { var a = 1; let b = 2; } console.log(a);//会输出结果 console.log(b);//会报错 b is not defined </script> </body> </html>
1.2let声明的变量不能够重复声明(不能够多次声明同一个变量)
var m = 1; var m = 2; let n = 3; console.log("m:",m);//输出2 console.log("n",n);//输出3 //这个时候代码是不会出错的 //但是我们把n重新使用let进行定义时 let n = 4; console.log("n",n);//Uncaught SyntaxError: Identifier 'n' has already been declared
1.3 var会变量提升,而let不会变量提升。
console.log(x);//会输出undefined var x = 10; console.log(y);// y is not defined let y = 20;
2 const 声明常量(它声明的变量不能被修改)
const a= 3; a = 100;//Assignment to constant variable. //当使用const声明变量时,不能够再次去修改它的值
3.结构表达式
//-----------数组结构---------------------- //使用let声明一个数组 /* 想要把数组中下标的值赋值给abc三个变量 传统的写法 */ let arr = [1,2,3]; let a = arr[0]; let b = arr[1]; let c = arr[2]; //这个是一个没有任何问题的输出 console.log(a,b,c) //使用结构表达式来写这个 let [a,b,c] = arr;//这个就是会默认把数组中的元素赋值到abc三个元素中 console.log(a,b,c);//再次输出效果是一致的 //----------对象结构------------ const person = { name:"张三", age:12, hobby:["吃饭","睡觉","打豆豆"] } //把数据提取出来赋值给三个变量 const name = person.name; const age = person.age; const hobby = person.hobby; console.log(name,age,hobby);// 传统写法是:张三 12 (3) ["吃饭", "睡觉", "打豆豆"] //使用结构表达式 const {name,age,hobby} = person; console.log(name,age,hobby);// 输出结果还是一致的:张三 12 (3) ["吃饭", "睡觉", "打豆豆"] //使用结构表达式还可以给变量重新起名 const {name:abc,age,hobby} = person; console.log(abc,age,hobby);// 输出结果还是一致的:张三 12 (3) ["吃饭", "睡觉", "打豆豆"]
4.字符串扩展 在es6中又新加了几个api
let str = "hello es"; //判断是否以某一个单词开头 console.log(str.startsWith('hello'));//true //判断是否以某一个单词结尾 console.log(str.endsWith("es"));//true //判断是否包含某一个单词 console.log(str.includes("e"));//true
5.字符串模板
5.1以前我们在定义多行字符串的时候我们需要写很多的双引号和加号,现在可以使用字符串模板来代替 符号就是键盘上数字1左边的反引号
let ss = `<div> <h1>你好世界</h1> </div>`; console.log(ss); 打印结果:会把每行的空格也会算上 <div> <h1>你好世界</h1> </div>
5.2 插值表达式
//插值表达式 const person = { name:"张三", age:"123", hobby:["吃饭","睡觉","打豆豆"] } const {name,age,hobby} = person; //使用插值表达式还可以调用方法 function fun(){ return "这是一个方法"; } let info = `我是${name},今年${age}岁了!!,我想说:${fun()}`; console.log(info);//我是张三,今年123岁了!!,我想说:这是一个方法
6.函数优化
6.1函数参数的默认值
//现在有一个需求,我们定义一个方法,参数有两个 /* 1.如果在调用时有参数为空值时我们需要给那个空值的参数加入一个默认值 */ function add(a,b){ //如果b的值为空值 会默认给1 b = b || 1; return a + b; } console.log(add(10));//输出11 //现在我们可以换一种写法 //es 6做的优化 function add2(a,b = 1){ return a + b; } console.log(add2(20));//输出21
6.2 不定长度参数 (可以传入的参数个数不是固定的)
可边长参数 int a...
//不定参数(可以传入的参数个数不是固定的) function fun1(...values){ console.log(values.length);//会根据传入的参数来输出参数的个数 } fun1(1,2,3,4,5);
6.3 箭头函数
//以前我们声明方法是这样的 var f1 = function(obj){ console.log(obj); } f1("你好世界") //--------------------------- //使用箭头函数的声明 /* 如果只有一个参数 obj就是参数名称 => 后面的就是方法体了 */ var f2 = obj => console.log(obj); f2("你好 es") //------------多个参数的写法----------------- /* 1.如果有多个参数 使用小括号把参数括起来 2.如果方法体中只有一条语句 可以直接写出来 这个函数会自动帮助我们返回 */ var f3 = (a,b) => a + b; console.log(f3(1,2)) //结果为3 //--------------方法体中有多条语句--------------- /* 1.如果有多个参数 可以使用()把参数括起来 2.如果方法体中有多个参数,可以是用{} 把着呢规格方法体括起来 */ var f4 = (a,b) => { var c = a+b; return c; } console.log(f4(3,4)) //结果为7
6.3.1 箭头函数的案例
const user = { name:"张三", age:12 } //现在想使用箭头函数的形式把user中的数据做一个输出 //param是参数 var f5 = (param) => { console.log(param.name,param.age); } //方法调用 f5(user); //----------------我们可以使用插值表达式的形式做优化-------------------- var f6 = ({name,age}) => { console.log(name,age); } f6(user)
7.对象优化
7.1 对象中数据的输出
const user = { name:"李四", age:22, hobby:['吃饭','睡觉','打豆豆'] } console.log(Object.keys(user));//返回所有的key值 ["name", "age", "hobby"] console.log(Object.values(user));//["李四", 22, Array(3)] /* [Array(2), Array(2), Array(2)] 0:(2) ["name", "李四"] 1: (2) ["age", 22] 2 :(2) ["hobby", Array(3)] */ console.log(Object.entries(user));//[Array(2), Array(2), Array(2)]
7.2对象之间的合并
const source1 = {a:1}; const source2 = {b:2}; const source3 = {c:3}; //第一个参数是目标对象,后面的对象都是参数 Object.assign(source1,source2,source3); console.log(source1);//{a: 1, b: 2, c: 3}
7.3 创建对象
var name = "王五"; var age = 22; //现在想要把这两个参数赋值到一个新的对象中 //传统的写法是 var stu1 = {name:name,age:age}; //使用es6的语法为 /* 如果新创建的对象中的属性和需要被赋值的属性值一致时就可以简化写法 */ var stu2 = {name,age}; console.log(stu2);
7.4在对象中定义方法
let o2 = { name:"田七", //传统的定义方法是这样的 //如果想使用对象中的参数时,需要使用this关键字来调用变量 eat1:function(food){ console.log(this.name+"在吃:"+food); }, //如果使用箭头函数在对象中创建方法时 //在箭头函数中this关键字是不能使用的,必须使用对象名点变量值获取 eat2:param => console.log(o2.name+"在吃:"+param), //还可以用第三种方法来实现 eat3(food){ console.log(o2.name+"在吃:"+food) } } o2.eat1("苹果");//田七在吃:苹果 o2.eat2("香蕉");//田七在吃:香蕉 o2.eat3("橘子");//田七在吃:橘子
7.5对象的扩展运算符
let o5 = {name:"张三"}; let o6 = {age:22}; let o7 = {age:33}; //深克隆,如果 被覆盖的对象中与目标对象中的属性名称一致,会被覆盖掉 o7 = {...o5,...o6}; console.log(o7);//{name: "张三", age: 22}
8.map和reduce的用法
/* map和reduce方法的使用 map() 接收一个函数,可以将源数组中的数据进行处理后返回给一个新的数组 */ var arr = ['a','b','c','d','e']; arr = arr.map((item)=>{ return item+"123"; }) console.log("arr:",arr); //简化写法 arr = arr.map(item => item+"123") //reduce() 为数组中的每一个元素都执行一个回调函数,不包括数组或只能怪被删除和未被赋值的元素 /* 可以有两个参数 callback,[intialValue] 可以传递一个函数,第二个参数可以传递初始值 在第一个参数中可以有4个参数 1.previousValue(上一次调用回调返回的值,或者是intialValue的值) 2.currentValue(数组中当前被处理的元素) 3.index 当前元素咋数组中的下标 4.array 调用reduce的方法的数组 arr.reduce(()=>{}) */ var arr = [1,2,3,4] var obj = arr.reduce((a,b)=>{ console.log("上一次处理后变成了:"+a); console.log("当前正在处理的元素:"+b); return a+b; }) console.log("obj:",obj)
9.promise
在javaScript的世界中,所有的代码都是单线程的,由于这个”缺陷“,导致javaScript所有网络操作,浏览器时间,必须是异步执行。异步执行可以使用回调函数实现,一旦有一连串的ajax请求a,b,c,d.....,后面的请求依赖前面的请求结果,就需要层层嵌套,非常容易造成上下文代码混乱,我们不得不非常小心翼翼的处理内层函数和外层函数的数据,一旦内层函数使用了外层函数的变量,这种混乱程度就会加剧。。。。总之,这种‘层叠上下文’的层层嵌套,着实增加了神经的经常程度。
9.1 传统案例演示
a) 创建用户信息 user.json
{ "id":1, "name":"张三", "password":123 }
b) 创建课程信息 course.json
{ "id":10, "name":"数学" }
c) 创建课程分数信息 course_score.json
{ "id":10, "score":90 }
d)传统的ajax请求分析
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <script> //1.查询当前用户信息 //2.按照当前用户的id查询课程 //3。按照当前课程id查询出分数信息 $.ajax({ url:`../mock/user.json`, success(data){ console.log("查询用户:",data) $.ajax({ url:`../mock/user_course_${data.id}.json`, success(data){ console.log("查询到的课程为:",data) $.ajax({ url:`../mock/course_score_${data.id}.json`, success(data){ console.log("查询到的成绩为:",data) } }) } }) } }) </script> </body> </html>
9.2使用promise封装之后的查询
resolve 成功之后的回调函数 reject 失败之后的回调函数 let p = new Promise((resolve,reject)=>{ $.ajax({ url:`../mock/user.json`, success(data){ console.log('查询到的结果为:',data) resolve(data); }, error(error){ reject(error); } }) }); p.then((obj)=>{ $.ajax({ url:`../mock/user_course_${obj.id}.json`, success(data){ console.log('查询到的课程信息为:',data) }, error(error){ } }) }).catch((error)=>{ }) //---------------------上面的写法只能查询一次---------------------------------------- //如果想复用 let p = new Promise((resolve,reject)=>{ $.ajax({ url:`../mock/user.json`, success(data){ console.log('查询到的结果为:',data) resolve(data); }, error(error){ reject(error); } }) }); p.then((obj)=>{ return new Promise((resolve,reject)=>{ $.ajax({ url:`../mock/user_course_${obj.id}.json`, success(data){ console.log('查询到的结果为:',data) resolve(data); }, error(error){ reject(error); } }) }) }).then(obj => { $.ajax({ url:`../mock/course_score_${obj.id}.json`, success(data){ console.log('查询到的结果为:',data) }, error(error){ } }) })
9.3封装promise方法
function get(url,data){ return new Promise((resolve,reject)=>{ $.ajax({ url:url, data:data, success(data){ resolve(data) }, error(error){ reject(error) } }) }) } // 改造之后重新实现 get(`../mock/user.json`).then(obj=>{ console.log("查询成功:",obj) return get(`../mock/user_course_${obj.id}.json`); }).then(obj=>{ console.log("查询成功:",obj) return get(`../mock/course_score_${obj.id}.json`); }).then(obj=>{ console.log("查询成功:",obj) })