一、ES6
新建项目:E:/study/前端/ES6
1、打开vscode,打开文件夹->新建文件夹 2、新建文件let.html,shift+!回车快速生成HTML文档 3、右键 open with live server【浏览器查看】
1、增加了let、const
以前只有var
let: 1、局部作用域 2、只能声明1次 3、let不存在变量提升【var变量使用时,声明可以在使用之后】 const: 1.声明之后不允许改变 2.一但声明必须初始化,否则会报错
demo:
1、let 声明的变量有严格局部作用域
<script>
// var声明的变量往往会越域
// let 声明的变量有严格局部作用域
{
var a = 1;
let b = 2;
}
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
</script>
2、let只能声明1次
<script>
// var可以声明多次
// let只能声明1次
var m = 1
var m = 2
let n = 3
let n = 4
console.log(m) // 2
console.log(n) // Identifier 'n' has already been dec lared
</script>
3、let不存在变量提升【var只要后面定义过了就可以】
<script>
// var会变量提升
// let不存在变量提升
console.log(x); // undefined T 【undefined是没有值】
varx=10;
console.log(y); //ReferenceError: y is not defined
lety=20;
</script>
4、const声明变量
<script>
// 1.声明之后不允许改变
// 2.一但声明必须初始化,否则会报错
const a = 1;
a = 3; //Uncaught TypeError: Assignment to constant variable .
</script>
2、解构表达式
解构:简化赋值操作
alt+shift+f代码整理
1、数组解构:简化将数组各项值赋给变量 // 数组解构 let arr = [1,2,3]; let a = arr[0]; let b = arr[1]; let c = arr[2]; let [x,y,z] = arr; //var [x,y,z] = arr; //const [x,y,z] = arr; console.log(a,b,c) console.log(x,y,z) 2、对象解构: // 对象解构 const person = { name: "jack", age: 21, language: ['java', 'js', 'css'] } // 原始的方法 // const name = person.name; // const age = person.age; // const language = person.language; // ES6方法: let {name, age, language} = person; //const {name, age, language} = person; //var {name, age, language} = person; console.log(name, age, language); 3、对象解构延伸:变量名可以修改 // name修改为abc let {name:abc, age, language} = person;
3、字符串扩展
1、几个新的API <script> let str = "hello.vue"; console.log(str.startsWith("hello"));//true console.log(str.endsWith(".vue"));//true console.log(str.includes("e")); //true console.log(str.includes("hello"));//true </script> 2、字符串模板 1)多行不用拼串 let ss = `<div> < span>hello world< span> </div>`; 2)解析层级表达式 const person = { name: "jack", age: 21, language: ['java', 'js', 'css'] } let {name:abc, age:Age, language} = person; let info = `我是${abc},今年${Age+10}岁,会用${person.language}`; console.log(info); 3)调用方法 function fun() { return "这是fun函数" } let infoFun = `调用函数:${fun()}`; console.log(infoFun);// 调用函数:这是fun函数
4、函数优化
1、函数参数默认值 2、不定参数:就是java中 ...args数组 3、箭头函数(声明一个变量=匿名函数,参数即函数参数,且可以配合解构使用)【调用该变量就是调用匿名函数】 4、箭头函数+解构
1、函数参数默认值 原始写法: //在ES6以前,我们无法给一个函数参数设置默认值,只能采用变通写法: function add(a, b) { //判断b是否为空,为空就给默认值1 b = b || 1; return a + b; } //传一个参数 console.log(add(10)); 新写法: //现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值 function add2(a, b = 1) { return a + b; } console.log(add2(10)); 2、不定参数:就是java中 ...args数组 // 不定参数 function fun(...args) { console.log(args.length); } fun(1,2,3,4); 3、箭头函数 // 箭头函数 单行: var print = obj => console.log(obj); print("hello"); var sum = (a,b) => a + b; console.log(sum(11,12)); // 多行,用小括号括起来 var sum2 = (a,b) => { c = a + b; return c + a; } console.log(sum2(11,12)); 4、箭头函数+解构 // 字符串模板 const person = { name: "jack", age: 21, language: ['java', 'js', 'css'] } // 箭头函数+解构 //var hello=(person)=>console.log("hello, " + person.name); 原来 var hello = ({name}) => console.log("hello, " + name); //解构,直接解析出对象的属性 hello(person);
5、对象优化
调用Object相关方法
1、对象优化:将对象转换成所需格式的对象 const person = { name: "jack", age: 21, language: ['java', 'js', 'css'] } console.log(Object.keys(person));// 键的数组 console.log(Object.values(person));// 值的数组 console.log(Object.entries(person));// 键值 数组 2、合并对象 const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { C: 3 }; //{a:1,b:2,c:3} Object.assign(target, source1, source2); console.log(target);//Object { a: 1, b: 2, C: 3 } 3、声明对象简写:如果变量名与属性名相同的话 const age = 23 const name = "张三" const person1 = { age: age, name: name } const person2 = { age, name } console.log(person2); 4、对象函数属性简写 三种函数写法: let person3 = { name: "jack", //以前: eat: function (food) { console.log(this.name + "在吃" + food); }, //箭头函数this不能使用,对象.属性 eat2: food => console.log(person3.name + "在吃" + food), eat3(food) { console.log(this.name + "在吃" + food) } } person3.eat("香蕉"); person3.eat2("苹果") person3.eat3("橘子") 5、对象拓展运算符 1)拷贝对象(深拷贝) let person4 = { name: "Amy", age: 15 } let someone = { ...person4 } console.log(someone) //{name:" Amy", age: 15 } 2)合并对象 后面的值会覆盖原有的值 let age1 = { age: 15 } let name1 = { name: " Amy" } let p2 = { name:"zhangsan" } p2 = { ...age1, ...name1 } console.log(p2)
6、map和reduce
很像java8,数组中新增了map和reduce方法
1、map():接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。 let arr = ['1', '20', '-5', '3']; // arr = arr . map( (item)=>{ return item * 2 }); arr = arr.map(item => item * 2); console.log(arr); 2、reduce(fun(previousValue, currentValue), initiaValue) //reduce()为数组中的每个元素 依次执行回调函数 ,不包括数组中被 删除或从未被赋值的元素, //[2, 40,-10, 6] /** arr.reduce(fun(previousValue, currentValue), initiaValue) 1、previousValue(上一次调用回调返回的值,或者是提供的初始值(initialValue)) 2、currentValue(数组中当前被处理 的元素) 3、index(当前元素在数组中的索引) 4、array(调用reduce 的数组) */ let result = arr.reduce((previousValue, currentValue) => { console.log("上一次处理后: " + previousValue); console.log("当前正在处理: " + currentValue); return previousValue + currentValue; }, 100); console.log(result)
reduce:
7、Promise
Promise对象,then((data)=>{})方法内部可以获得上一次请求返回的data值,所以可以根据data继续发送ajax请求
在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现。一旦有一连串的ajax请求a,b,..后面的请求依赖前面的请求结果,就需要层层嵌套。这种缩进和层层嵌套的方式,非常容易造成上下文代码混乱,我们不得不非常小心翼翼处理内层函数与外层函数的数据,一旦内层函数使用了上层函数的变量,这种混乱程度就会加剧..总之,这种"层叠.上下文的层层嵌套方式,着实增加了神经的紧张程度。
总结:就是代码缩进容易造成代码混乱,内层调用上层的变量
案例:用户登录,并展示该用户的各科成绩。在页面发送两次请求:
1.查询用户,查询成功说明可以登录
2.查询用户成功,查询科目
3.根据科目的查询结果,获取去成绩
1、原始 //1、查出当前用户信息 //2、按照当前用户的id查出他的课程 //3、按照当前课程id查出分数 $.ajax({ url: "mock/user.json", success(data) { console.log("查询用户:", data); $.ajax({ url: `mock/user_corse_${data.id}.json`, success(data) { console.log("查询到课程:", data); $.ajax({ url: `mock/corse_score_${data.id}.json`, success(data) { console.log("查询到分数:", data); }, error(error) { console.log("出现异常了:" + error); } }); }, error(error) { console.log("出现异常了:" + error); } }); }, error(error) { console.log("出现异常了:" + error); } }); 2、Promise可以封装异步操作,只有成功了then方法才会被执行【resolve和reject应该是两个回调函数,resolve里面调用了then方法】 let p = new Promise((resolve, reject) => { //1、异步操作 $.ajax({ url: "mock/user.json", success: function (data) { console.log("查询用户成功:", data) resolve(data); }, error: function (err) { reject(err); } }); }); p.then((obj) => { return new Promise((resolve, reject) => { $.ajax({ url: `mock/user_corse_${obj.id}.json`, success: function (data) { console.log("查询用户课程成功:", data) resolve(data); }, error: function (err) { reject(err) } }); }) }).then((data) => { console.log("上一步的结果", data) $.ajax({ url: `mock/corse_score_${data.id}.json`, success: function (data) { console.log("查询课程得分成功:", data) }, error: function (err) { } }); }) 3、封装返回Promise对象的创建,简化代码 function get(url, data) { return new Promise((resolve, reject) => { $.ajax({ url: url, data: data, success: function (data) { resolve(data); }, error: function (err) { reject(err) } }) }); } get("mock/user.json") .then((data) => { console.log("用户查询成功~~~:", data) return get(`mock/user_corse_${data.id}.json`); }) .then((data) => { console.log("课程查询成功~~~:", data) return get(`mock/corse_score_${data.id}.json`); }) .then((data)=>{ console.log("课程成绩查询成功~~~:", data) }) .catch((err)=>{ console.log("出现异常",err) });
遇到的问题:file协议无法跨域: https://juejin.im/post/6844903965411246093
同源策略(Same origin policy),是出于安全而诞生的一种约定,规定了只能在本域内进行资源访问。所谓同源是指"协议+域名+端口"三者相同。
1、使用live server 2、http请求的话,请求头需要带origin,并在服务端验证合法 request header 的 origin 必须合法
8、模块化
就是把script代码从html中抽离出来放到.js文件中,然后js文件的对象、数组、基本类型变量、函数可以被导出被其他js文件复用,这就称为模块化
1、 hello.js // export const util = { // sum(a, b) { // return a + b; // } // } // export {util} 默认时,import与这里要写的一样 export default { sum(a, b) { return a + b; } } //`export`不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、对象。 user.js var name = "jack" var age = 21 function add(a,b){ return a + b; } export {name,age,add} main.js import abc from "./hello.js" import {name,add} from "./user.js" abc.sum(1,2); console.log(name); add(1,3);