老样子。复制上来的图片都没了,想看原版可以移步对应资源下载(资源刚上传,还在审核中)
(免费)菜狗学前端之ES6+笔记https://download.csdn.net/download/m0_58355897/89135424
一 解构赋值
解构赋值 解构指的是把一个数据结构拆开 赋值则是把其赋值给另外一个一摸一样的数据结构 三类 1.数组的解构赋值 2.对象的解构赋值 3.字符串的解构赋值 |
(一) 数组的解构赋值
数组解构的核心是 结构保持一致 var names = ['小强', '张三', '李四'] var [name1, name2, name3] = names PS:不完全解构 let arr2 = [1, 2] let [num1] = arr2 |
HTML <script> // 数组解构的核心是 结构保持一致
var names = ['小强', '张三', '李四']
// 需求:想让这里面的名字拿出来 分别命名为name1 name2 name3 // 之前写法:var name1=names[0]
// 可以使用解构赋值来实现 注意保持结构一模一样 var [name1, name2, name3] = names console.log(name1);//小强 console.log(name2);//张三 console.log(name3);//李四 </script>
<script> var arr1 = [ {userName: '旺财', age: 18 }, [99, 88], 111 ]
// 需求:把数据拿出来 userName age score id var [{ userName, age }, score, id] = arr1 console.log(userName);//旺财 console.log(age);//18 console.log(score);//[99, 88] console.log(id);//111 </script>
<script> let arr2 = [1, 2] // 不完全解构(即不完全拿到数据) let [num1] = arr2 console.log(num1);//1
let arr3 = [1] let [num2, num3] = arr3 console.log(num2);//1 console.log(num3);//und </script> |
(二) 对象的解构赋值
对象解构的核心是 属性名保持一致 let obj = { username: '旺财', age: 18 } 当对象的属性名和属性值一样时 可以省略为一个 let { username: username, age: age } = obj let { username, age } = obj PS: 当对象解构赋值时,不能修改里面的value值 但是可以在解构赋值的过程中新添加一个值 let obj2 = { username1: '旺财', age1: 18, sex1: '女' }; let { username1, age1, sex1 = '男' } = obj2 |
HTML <script> let obj3 = { arr: [ 'hello', { msg: 'es6' } ] }
let { arr: [ str1, { msg: str2 } ] } = obj3; console.log(str1, str2);//hello es6 </script> <script> let obj4 = { f1: function () { console.log(1); }, f2: function () { console.log(2); } }
// 对象的不完全解构
let { f1 } = obj4; f1()// 1 f2()// f2 is not defined </script> |
(三) 字符串的解构赋值
字符串的解构赋值 某种意义上 可以参照数组 var str = 'h e' // 左边是[]罩起来不是'' let [a, b, c] = str console.log(a);//h console.log(f);// console.log(g);//E |
(四) 函数形参的解构赋值
JavaScript function bar([x, y]) { console.log(x); console.log(y); } // [x, y]=[1, 2] bar([1, 2])
function fn({ x, y, z = 3 }) { console.log(x); console.log(y); console.log(z); } // { x, y, z = 3 }={ x: 1, y: 2} fn({ x: 1, y: 2 }) |
二 展开运算符和rest运算符
(一) 展开运算符
展开运算符 又叫 拓展运算符 形式:... 可以把一个数组转换为用逗号分开的序列 |
JavaScript // 需求: 将两个数组进行合并 var arr1 = [1, 2, 3] var arr2 = [4, 5, 6] var arr3 = [...arr1, ...arr2] console.log(arr3);//[1, 2, 3, 4, 5, 6] // 需求:找最大值 var arr4 = [2, 4, 6, 57, 3, 2, 6, 78, 54, 3, 2]; console.log(Math.max(...arr4));//78 |
(二) rest运算符
JavaScript // 当前你要定义一个函数 但是这个函数的参数不确定 function fn(...args) { console.log(args); } fn([1, 2], 3) // 解构赋值+res运算符... 只能获取前几个值 var arr1 = [1, 2, 3, 4] //A rest element must be last in a destructuring pattern // let [a, ...b, c] = arr1 let [a, b, ...c] = arr1 console.log(a);//1 console.log(b);//2 console.log(...c);//3 4 console.log(c);//[3 4] |
(三)展开和rest运算符区别
当...出现在赋值运算符右侧/作为函数实参时:拓展(展开)运算符 var arr3 = [...arr1, ...arr2] Math.max(...arr4) 当...出现在赋值运算符左侧/作为函数形参时:rest运算符 let [a, b, ...c] = arr1 function fn(...args) { console.log(args); } PS: args-- arguments 参数 |
三 浅拷贝对象Object.assign()
Object.assign() --浅拷贝 浅拷贝--拷贝了地址,共用一个堆空间,所以一个改变其他随之改变 作用:将源对象的所有可枚举的属性 复制到目标对象 需要2个参数 第一个参数是目标参数 -- obj3 后续的参数都是源对象 -- obj1,obj2 PS: Object.assign VS cloneNode 浅克隆-cloneNode() 仅克隆该节点,不克隆其中后代节点 深克隆-cloneNode(true) 将节点的后代节点也克隆 |
JavaScript var obj1 = { name: 'zhangsan', address: '郑州', hobby: '写代码' } var obj2 = { age: 18 } Object.assign(obj3, obj1, obj2) console.log(obj3); // Object.assign -- 浅拷贝 // 深拷贝(开辟了一个新的堆地址,各自独立拥有堆空间) // 浅拷贝(拷贝了地址,共用一个堆空间) var obj7 = { address: { city: "郑州" } } var obj8 = {} Object.assign(obj8, obj7) // 改的是obj8属性但是obj7随之改变--因为浅拷贝,指向同一地址 obj8.address.city = "上海" console.log(obj7);//上海 |
四 Object.defineProperty()
(一) 给对象添加属性并添加对应配置项
JavaScript var obj = {} // Object.defineProperty(obj, 'age', { value: 18, // 是否可被枚举 enumerable: false //默认值是false 不可被枚举 }) console.log(obj); // 不可被枚举 for in也循环不到 for (let key in obj) { console.log(obj[key]); } // 不可被枚举 不能被复制 let obj6 = {} Object.assign(obj6, obj) console.log(obj6); |
(二) 监听对象的多个属性 循环遍历
JavaScript let obj1 = { name: '张三', age: 18, money: 5000 } for (let key in obj1) { Object.defineProperty(obj1, key, { set(value) { // value -- 被修改的新值 console.log('set被调用了'); console.log('set的新值:' + value); }, get() { console.log('get被调用了'); } }) } console.log(obj1.name);//get被调用了 obj1.money = 3000;//set被调用了 set的新值:3000 |
五 Proxy代理
proxy --代理 代理模式 --程序设计的一种设计模式 监听一个对象上的属性 Proxy用于修改某些操作的默认行为, 可以理解在目标对象之前,设置了一个拦截 ,如果外界去访问对象(数据)的时候,都需要通过这层拦截,就可以对外界的访问进行过滤和改写 |
(一) Proxy代理相关概念
1.Proxy作用
1.屏蔽原始数据 2.保障原始数据安全
2.Proxy构造器中参数
第一个参数 代理对象 第二个参数 配置项
(二) Proxy捕获器
JavaScript let obj = { name: '李四', age: 18 } let objProxy = new Proxy(obj, { // 监听获取动作 get: function (target, key) { console.log('get被执行了');
}, // 监听设置动作 set: function (target, key, newValue) { console.log('set被执行了'); console.log(newValue); }, // 监听in动作 has: function (target, key) { console.log('in捕获器'); return key in target }, // 监听删除动作 deleteProperty: function (target, key) { console.log('delete触发了'); } })
// in 判断属性有没有在这个对象上 或者说 对象上有没有此属性 console.log('name' in objProxy);//true delete objProxy.name//不影响obj console.log(obj); |
六 class
(一)class概念及使用
class是一个语法糖,就是你相同代码的功能可以简写 箭头函数也是语法糖 |
JavaScript class Student { // 如果想要给这个类的对象添加属性的时候 constructor(name, age) { // 挂载在对象身上的私有属性 this.name = name this.age = age // constructor的作用 // 1.创建一个对象 // 2.将Person的prototype赋值给创建出来的实例化对象 p.__proto__=Person.prototype // 3.让this指向对象p--让this指向p // 4.执行内部代码 } // 挂载在原型对象上 公有属性 say() { console.log('say...'); } } // class继承extends class Mointor extends Student { constructor(name, age, id) { super(name, age) this.id = id } } let m = new Mointor("张三", 18, 1) console.log(m); |
(二)class设置器和访问器
JavaScript class Student { constructor(address, age) { this._address = address this.age = age } // 访问器 get address() { console.log('get被调用了'); return this._address } // 设置器 set address(value) { console.log('set被调用了'); this._address = value // console.log('设置值:' + value); } }
let stu = new Student('郑州', 18) console.log(stu._address);//加上下划线相当于正常的访问属性 console.log(stu.address);//不加下划线 相当于通过get set去访问的
// stu._address = '上海' stu.address = '上海'; console.log(stu); |
(三)class静态属性|方法 static
静态属性|方法 static - 如果在一个方法前,加上static关键字,就表示该方法不会被实例继承
- 只能通过构造器去访问 不能通过实例之后的对象来访问
且静态方法里的this只能访问静态属性 |
HTML <script> class Person { // 静态属性/方法 static say() { console.log(11); } } // 静态属性 只能通过构造器去访问 不能通过实例之后的对象来访问 Person.say() // 注意:不能通过实例之后的对象变量来访问 let p = new Person() p.say() //say is not a function </script> <script> // 静态方法里的this只能访问静态属性 class Person { // 公共属性 static names = "张三"//静态属性 age = 18 static show() { console.log(this.names);//张三 console.log(this.age);//und console.log(Person === this);//true } } Person.show()//张三 und |
七 Symbol()
问题:协同开发 对象中属性名冲突 问题本质原因:属性名的不唯一性 解决方法:Symbol() 属性名可重复 只是书写方式不同:属性名需加[] let mySymbol1 = Symbol('mySymbol1') mySymbol1: 'mySymbol1', [mySymbol1]: '第一种方式' 调用方式不同:一个对象打点,一个对象[] console.log(obj.mySymbol1); console.log(obj[mySymbol1]); |
(一) Symbol()特点
JavaScript let s3 = Symbol('s') let s4 = Symbol('s') console.log(s3);//Symbol(s) console.log(s3 == s4);//false |
(二) 通过Symbol()避免属性名冲突-三种方式
JavaScript let obj = {} // 第一种方式[mySymbol1]: '第一种方式' let mySymbol1 = Symbol('mySymbol1') obj = { mySymbol1: 'mySymbol1', [mySymbol1]: '第一种方式' } // 这样属性名就可重复,只是调用方式不同 console.log(obj.mySymbol1); console.log(obj[mySymbol1]);
// 第二种方式 obj[mySymbol2] = '第二种方式'; let mySymbol2 = Symbol('mySymbol2') obj[mySymbol2] = '第二种方式'; console.log(obj[mySymbol2]);
// 第三种方式 Object.defineProperty() let mySymbol3 = Symbol('mySymbol3') Object.defineProperty(obj, mySymbol3, { value: '第三种方式', enumerable:true }) console.log(obj[mySymbol3]);
console.log(obj); |
八 Set和Map
Es6中 新增了两种结构 set map weakset weakmap 应用场景: Map:适用于需要将键映射到值的情况,例如管理用户权限、存储对象之间的关联关系等 Set:适用于需要存储一组唯一值的情况,例如去重数组中的重复项、跟踪一组唯一的项目等 set和数组结构相似 但是set可以去重,set里没有重复的元素 |
(一) Set
1.Set操作方法
1.add(value) 返回Set结构本身
2.delete(value) 返回布尔值-删除是否成功
3.clear() 清除所有成员 返回值undefined
4.has(value) 返回布尔值-参数否是Set的成员
PS:Set实例化对象添加重复元素无效
JavaScript let s = new Set() s.add(1) s.add(1)//添加重复元素无效 console.log(s.add(2));//Set(2) {1, 2} console.log(s.has(2));//true console.log(s.delete(2));//true s.clear(); console.log(s);//Set(0) {size: 0} |
2.Set转Array--Array.from()
JavaScript let s = new Set() s.add(1) s.add(2) s.add(3) console.log(s); //通过Array.from()方法将Set转为Array let arr = Array.from(s) console.log(arr); |
3.WeakSet-成员类型只能是对象类型
WeakSet 和Set类似的另一个数据结构 也是内部成员不能重复 1.WeakSet成员类型只能是对象类型 不能放其他类型 2.WeakSet不能遍历 如果遍历了 获取其中的元素 那么里面的对象无法被正常销毁 |
JavaScript let weakset = new WeakSet() let obj1 = { name: '1' } let obj2 = { name: '2' } weakset.add(obj1) weakset.add(obj2) // weakset.add(1)//Invalid value used in weak set console.log(weakset); |
(二) Map
1.Map操作方法
set(key,value)
get(key)
has(key)
delete(key)
clear()
JavaScript let map = new Map() let obj = { city: "郑州" } map.set(obj, '大玉米') console.log(map.set('开封', '清明上河园'));//Map(2) {{…} => '大玉米', '开封' => '清明上河园'} console.log(map.has(obj));//true console.log(map.get(obj));//大玉米 console.log(map.delete(obj));//true console.log(map); //Map(1) {'开封' => '清明上河园'} |
2.WeakMap-用key只能是对象类型
1.WeakMap 用对象作为key 不能使用基本数据类型作为key 2.WeakMap不能遍历 |
九 Promise
(一) 前置知识--JS代码执行顺序
js代码执行顺序:同步代码-->异步代码(微任务->宏任务)
异步任务 宏任务和微任务 特点:先微后宏
- 同步任务
- 异步任务(宏任务和微任务)
- 微任务:Promise.then、Promise、async/await
- 宏任务:定时器(setTimeout setInterval)、事件监听、Ajax、DOM事件
PS:
1.async内遇到await先执行await,其中有异步代码的话--阻塞async后面代码执行,但不阻塞async外代码继续执行
2.promise执行resolve()或者reject()改变状态时才会把其then方法放进微任务队列
3.Event Loop
(二) 旧解决异步问题方式-回调函数
异步问题:js单线程执行,如何实现异步
之前的方式:回调函数
缺点:过多函数嵌套导致出现”回调地狱”
JavaScript // 最早解决异步问题:靠回调函数 // 1.设计这样的一个函数 function execCode(counter, successCallback, failureCallback) { // 异步任务 setTimeout(() => { if (counter > 0) { // counter可以计算的情况 let total = 0 for (let i = 0; i < counter; i++) { total += i } // 在某一个时刻只需要回调传入的函数 successCallback(total) } else { // 失败情况, counter有问题 failureCallback(`${counter}值有问题`) } }, 3000) } // 2.ES5之前,处理异步的代码都是这样封装 execCode(100, (value) => { console.log("本次执行成功了:", value) }, (err) => { console.log("本次执行失败了:", err) }); |
(三) Promise相关概念
1.promise概念及作用
概念:promise是解决异步编程的一种解决方案,合理且强大 可以替代传统的解决方案-回调函数
好处:异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
作用:主要是为了解决异步的问题 让异步代码先执行
PS:promise可以解决异步的问题,但不能说promise本身是异步的
2.Promise对象特点
3.Promise对象的三种状态--PromiseState属性
- 等待状态:pending 默认创建出来promise出于等待状态
- 成功状态:fulfilled 当调用resolve函数时,promise从等待态变为成功态
- 失败状态:rejected 当调用reject函数时,promise从等待态变为失败态
PS:
对一个Promise对象来说 成功或失败后 不能再次改变其状态
即只能从等待状态转为成功状态 / 从等待状态转为失败状态
JavaScript // 1.等待态 pending 默认 let p1 = new Promise((resolve, reject) => {
}) console.log(p1);
// 2.成功态 fulfilled 调用resolve() let p2 = new Promise((resolve, reject) => { resolve('resolve') }) console.log(p2);
// 3.失败态 rejected 调用reject() let p3 = new Promise((resolve, reject) => { reject('reject') }) console.log(p2);
// 注意事项: // 对一个Promise对象来说 成功或失败后 不能再次改变其状态 // 即只能从等待状态转为成功状态 / 从等待状态转为失败状态 let p4 = new Promise((resolve, reject) => { resolve('resolve') reject('reject')//无效 }) console.log(p4);//状态仍为fulfilled成功状态 |
4.Promise对象的三种终值--PromiseResult属性
- pending --终值 undefined
- fulfilled --终值 成功的结果
- rejected --终值 失败的原因
(四) Promise的then方法
1.每个promise对象都有then方法
- then的作用:then可以处理promise对象成功或失败之后的事情
- then的2个参数:分别对应成功后的回调和失败后的回调
JavaScript let p1 = new Promise((resolve, reject) => { resolve('成功') }) // 传递一个参数--指的是成功的结果 PromiseResult p1.then((result) => { console.log(result); })
let p2 = new Promise((resolve, reject) => { reject('失败') }) // 传递两个参数--一成功的结果 一失败的结果 PromiseResult p2.then((result) => { console.log(result); }, (error) => { console.log(error); }) |
2.then的返回值
then的返回值是一个新的promise对象 - 返回成功态的promsie:上一个then返回一个普通的值(包含und)
- 返回失败态的promise对象:上一块代码报错
- 返回新的promise对象:then的返回值是一个新的promise对象
|
- 返回成功态的promsie:上一个then返回一个普通的值(包含und)
JavaScript let p1 = new Promise((resolve, reject) => { // reject('失败') resolve('成功') }) // 上一个then返回一个普通的值(包含und) 新的promise是成功的promsie let p2 = p1.then((result) => { console.log(result);//成功 }, (error) => { console.log(error); }) console.log(p1); console.log(p2); |
- 返回失败态的promise对象:上一块代码报错
JavaScript let p1 = new Promise((resolve, reject) => { // reject('失败') resolve('成功') }) let p2 = p1.then((result) => { console.log(result);//成功 throw new Error('出了小错') }, (error) => { console.log(error);//失败 throw new Error('出了小错') }) console.log(p1); console.log(p2); |
- 返回新的promise对象:then的返回值是一个新的promise对象
JavaScript let a = new Promise((resolve, reject) => { resolve('成功') // reject('失败') }) let a1 = a.then(result => { // 在成功态里面返回了一个失败态的promise console.log(result); let a3 = new Promise((resolve, reject) => { reject('失败') }) return a3 }, error => { console.log(error); // 在失败态里面返回了一个成功态的promise let a4 = new Promise((resolve, reject) => { resolve('成功') }) return a4 }) console.log(a1); |
3.then的顺延
- finally -- 最终都会走这个finally
|
- 少写一个|不写参数
JavaScript
// 当你promise对象的then中没有成功或者失败的处理 那么会顺延到下一个promise对象中做处理
let p2 = new Promise((resolve, reject) => { reject('失败') }) p2.then(result => { console.log(1); }).then(result => { console.log(3); }, errer => { console.log(4); })
// 1.2不写参数 let p3 = new Promise((resolve, reject) => { resolve('成功') }) p3.then().then(result => { console.log(3); }, error => { console.log(4); }) |
- catch 把then失败的情况单独拎出来
JavaScript let p4 = new Promise((resolve, reject) => { reject('失败') }) p4.then(result => { console.log('处理成功'); }).catch(error => { console.log('处理失败'); }) |
- finally 最终都会走这个finally
JavaScript let p5 = new Promise((resolve, reject) => { reject('失败') }) p5.then(result => { console.log('处理成功'); }).catch(error => { console.log('处理失败'); }).then(result => { // 前面return的值,result拿到的是上一个promise的终值 console.log(result);//und }).finally(() => { console.log('最终'); }) |
(五) 利用Promise解决异步问题
JavaScript function fn(num) { // 同步代码 return new Promise((resolve, reject) => { setTimeout(function () { console.log('异步1'); if (num >= 50) { resolve('v我50') } else { reject('v你50') } }, 1000) console.log('同步1'); }) }
// .then函数内 异步代码 fn(49).then((result) => { console.log(result); }, (error) => { console.log('异步2'); console.log(error); })//v你50
console.log('同步2'); //同步1 同步2 异步1 异步2 v你50 |
(六) Promise的resolve的实参
1.普通参数
2.参数是一promise对象
JavaScript let p2 = new Promise((resolve, reject) => { reject('失败1') }) resolve(p2) |
3.是一个thenable (一不完整的promise对象)
thenable:就是一个对象中有一个then函数
JavaScript resolve({ //then: function(resolve, reject) {} then(resolve, reject) { reject('失败2') } }) |
(七) Promise的静态方法
1、2. resolve、reject
JavaScript // 最常规的两个静态方法 1.resolve 2.reject // 可以直接创建一个成功或者失败的promise对象 let p1 = Promise.resolve('成功') console.log(p1);
let p2 = Promise.reject('失败') console.log(p2); |
3.all
JavaScript // 3.all // 表示所有的promise都成功后 得到所有promise成功的结果 // 如果有一个失败 则直接得到最先失败的promise的结果 // all参数传递的是一个数组的格式
let p3 = new Promise((resolve, reject) => { setTimeout(() => { // resolve('p3成功') reject('p3失败') }, 3000) }) let p4 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p4成功') }, 2000) }) let p5 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p5成功') }, 4000) }) Promise.all([p3, p4, p5]).then(result => { console.log(result); }).catch(error => { console.log('走了catch'); console.log(error); }) //['p3成功', 'p4成功', 'p5成功'] |
4.any
JavaScript // 4.any // 等待最先成功的promise 或者 得到所有Promise都失败(All promises were rejected)
let p3 = new Promise((resolve, reject) => { setTimeout(() => { // resolve('p3成功') reject('p3失败') }, 3000) }) let p4 = new Promise((resolve, reject) => { setTimeout(() => { // resolve('p4成功') reject('p4失败') }, 2000) }) let p5 = new Promise((resolve, reject) => { setTimeout(() => { // resolve('p5成功') reject('p5失败') }, 4000) }) Promise.any([p4, p5, p3]).then(result => { console.log('走了then'); console.log(result); }).catch(error => { console.log('走了catch'); console.log(error);//All promises were rejected }) |
5.allSettled
JavaScript // 5. allSettled // 表示所有的promise的结果 不管成功还是失败 最后都会走成功态方法result=>{} let p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p3成功') }, 3000) }) let p4 = new Promise((resolve, reject) => { setTimeout(() => { // resolve('p4成功') reject('p3失败') }, 2000) }) let p5 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p5成功') }, 4000) }) Promise.allSettled([p4, p5, p3]).then(result => { console.log('走了then'); console.log(result); }).catch(error => { console.log('走了catch'); console.log(error); }) |
6.race
JavaScript // 6. race // 等待最先拿到状态的promise结果 不管成功还是失败 let p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p3成功') // reject('p3失败') }, 3000) }) let p4 = new Promise((resolve, reject) => { setTimeout(() => { // resolve('p4成功') reject('p4失败') }, 2000) }) let p5 = new Promise((resolve, reject) => { setTimeout(() => { resolve('p5成功') }, 4000) }) Promise.race([p5, p4, p3]).then(result => { console.log('走了then'); console.log(result); }).catch(error => { console.log('走了catch'); console.log(error);
}) |
十 async+await(≈Promise)
- async关键字(修饰符) 是异步的简写 用于声明一个异步函数
- 函数用async修饰后,变成异步函数,会返回一个promise对象
- await 不能单独使用,必须在async的修饰下使用
个人理解: - async内遇到await时,若await的函数中有异步代码则不再向下执行-async内部阻塞,但是async外面的同步代码仍正常运行
|
(一) async
1.async的几种写法
具名函数、匿名函数、箭头函数、使用class声明类
JavaScript // 具名函数的写法 async function fn() { console.log(123); } console.log(fn());
// 匿名函数的写法 let gn = async function () {
} console.log(gn());
// 箭头函数的写法 let tn = async () => { } console.log(tn());
// 使用class声明类 class Person { async eat() {
} } let p = new Person() console.log(p.eat()); |
2.async函数return返回值-对应promise状态
- 返回是一个普通值/不返回(即und) 那么整个promise状态是成功态
- 返回的是一个promise对象 内部的promise对象的最终状态会影响到外部
- 返回的是一个thenable对象 内部的thenable对象的最终状态会影响到外部
return {
then(resolve, reject) {
reject('失败')
}
}
- 4.代码中有异常,抛出错误(代码运行并不终止) 那么整个promise就是一个失败态
JavaScript async function foo() { // 1.返回是一个普通值 状态是成功态 return 123
// 2.返回的是一个promise对象 内部的promise对象的最终状态会影响到外部 // return new Promise((resolve, reject) => { // // resolve('成功') // reject('失败') // })
// 3.返回的是一个thenable对象 内部的thenable对象的最终状态会影响到外部 // return { // then(resolve, reject) { // reject('失败') // } // }
// 4.代码中有异常,抛出错误,那么整个promise就是一个失败态 // console.log(a); } console.log(foo()); foo().then(result => { console.log(result); }, err => { console.log(err); }) console.log('hhhh');
// Promise // hhhh // 123 |
(二) await
await 不能单独使用,必须在async的修饰下使用 PS: - await等待的是一个成功的promise的结果,拿到成功的结果,才会执行async内的后续代码否则中断不再执行
- await执行过程中遇到异步代码会阻塞不再向下执行async内部代码,但同时不影响async外部剩下同步代码的执行
|
JavaScript // await等待的是一个成功的promise的结果,拿到成功的结果,才会执行async内的后续代码 // async+await可替换new Promise()+then async function foo() { await new Promise((resolve, reject) => { // resolve('成功') reject('失败')//微任务 console.log(1); }) console.log(111);//未执行 } foo()//1 console.log('async外的同步代码');//async外的同步代码 |
十一 ES6+中的其他方法
(一) Object.keys和Object.values和Object.entries
通过 Object.keys 获取一个对象所有的key
通过 Object.values 来获取所有的value值
通过 Object.entries -- 对对象、数组/字符串的操作
对对象:获取所有的[key,value]值
对数组/字符串:获取所有的索引+数组/字符串对应项
JavaScript let obj = { name: 'wc', age: 18, height: 180, address: 'zz' } console.log(Object.keys(obj)); console.log(Object.values(obj)); console.log(Object.entries(obj)); console.log(Object.entries(['zs', 'ls'])); console.log(Object.entries("hi")); |
(二) String的padStart()|padStart()
String Padding 某些字符串进行前后的填充,来实现某种格式化效果
应用场景:比如需要对身份证、银行卡的前面位数进行隐藏
JavaScript let cardNumber = '410233043254032403'; // 截取前14位 let sliceNumber = cardNumber.slice(0, 14) // 总长度cardNumber.length,减去sliceNumber.length剩余位数用'*'替换 cardNumber = sliceNumber.padEnd(cardNumber.length, '*') console.log(cardNumber);//41023304325403**** |
(三)flat() 按指定的深度递归遍历数组
JavaScript // 三维数组 let nums = [ 10, 20, [111, 222], [333, 444], [[123, 321, ["a", "b"]], [456, 654]] ] // flat(0)深度为0 let numarr = nums.flat(0) console.log(numarr); // nums.flat()与nums.flat(1)都是深度为1 numarr = nums.flat(1) console.log(numarr); numarr = nums.flat(2) console.log(numarr); //深度Infinity-无穷大 numarr = nums.flat(Infinity) console.log(numarr); |
(四)||和??
- || 逻辑或运算符
- 如果第一操作值为假值(null、undefined、false、空字符串、0、NaN), 那么就会返回第二个值。如果第一个值为真值,返回第一个值。
- ?? 空值合并操作符
- 如果第一个操作数是空值(例如 null 或 undefined),那么它就会返回第二个操作数的值。反之返回第一个值
- ||逻辑或运算符 VS ??空值合并操作符
- 值判断范围不同: || 判断是否为假值 , 而 ?? 主要针对null undefined
- 用途稍有不同:|| 是逻辑运算符偏向逻辑处理, ??主要为了简化代码
JavaScript let info1 = 0 info1 = info1 || '默认值' console.log(info1);//默认值
let info2 = 0 info2 = info2 ?? '默认值' console.log(info2);//0 |
十二 箭头函数
(一)箭头函数实例
JavaScript var fn = () => { // {} 函数体 // () 形参列表 }
// 当一个参数的时候 省略括号() var f1 = i => { }
// 当函数体只有一句话的时候的时候 省略{} var f1 = i => console.log(i);
// 当只有一个返回值的时候 return省略 var f3 = i => 10
// 当你返回的是一个对象 需要在函数体外部加上括号 var f4 = i => ({ a: 1 })
function Person(name) { this.name = name; }
// 注意:箭头函数内没有this let Person = (name) => { this.name = name; } let p = new Person() |
(二)哪些地方不能使用箭头函数(涉及this指向问题)
1.不能作为构造器,因为不能new(用this赋值) 2.在ES6中声明class类里的constructor函数,不能使用箭头函数 3.给原型对象添加方法的时候 不要使用箭头函数 |
十三 声明变量 let|const
1.let声明的特点
1.let声明不会提升 (提升 但是没有初始化)
2.let声明的变量不会挂载在window上
3.let不能对变量重复声明
4.let会和{}形成块级作用域
2.const声明(常量)特点
1.不会提升 (提升 但是没有初始化)
2.和{}形成块级作用域
3.不能重复声明
4.不能挂载在window(Go)上
5.不能被改变
6.声明的时候必须赋值
(二) let形成暂时性死区
JavaScript // 形成了暂时性死区 // 由于let提升但是未初始化 导致在一片区域内 不能按照作用域链向上寻找变量 // 这个区域叫暂时性死区 var a = 1 { console.log(a);//Cannot access 'a' before initialization let a = 2;//let声明提升但未初始化 } |