javascript 提出新规范
ECMAScript 6.0 简称 ES6是 JavaScript 语言的下一代标准,在 2015 年 6 月正式发布了。之后的版本全称为es6它可以用来编写复杂的大型应用程序,因为方便快捷,很快成为企业级开发语言。
let
let 是 ES6 中新增加的用于声明变量
的关键字,它具有如下特点:
-
不存在变量提升,不能先使用再声明
-
只在块级作用域有效
-
不能重复声明
const
const 也是 ES6 中新增加的用于声明变量
的关键字,它主要用来声明常量。它具有如下特点:
2.4 暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
避免报错 需要 if判断或者短路运算避免
6. 可选链 及 短路运算
可选链 ?. 是一种 访问嵌套对象属性的防错误方法 。即使中间的属性不存在,也不会出现错误。 如果可选链 ?. 前面部分是 undefined 或者 n
//es6 可选链
//不确定 obj 对象里的结构时
//规避 嵌套结构对象引用报错的问题
let obj = {
person:{
name:{
age:18
}
}
}if(obj.person){
if(obj.person.name){
console.log(obj.person.name.age)
}
}
console.log(obj.person && obj.person.name && obj.person.name.age)
console.log(obj.person?.name?.age)ull,它会停止运算并返回 undefined。
-
声明常量时必须赋值
-
只在块级作用域有效
-
赋值后,值不能修改
-
如果是对象等复杂数据类型,不能更改地址,但是可以更改对象中属性的值。
var、let、const 的区别
-
var 声明的变量作用域在所处的函数内(函数作用域),let 和 const 声明的变量作用域在所处的大括号内(块级作用域)。
-
var 声明的变量存在变量提升现象,let 和 const 声明的变量不存在变量提升现象。
-
const 声明变量时必须要赋值,赋值之后不能再重新赋值。
-
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
作用域及作用域链
3. 箭头函数
箭头函数是es6中新增的函数简写的一种方式.目的是使代码更高雅简洁。
-
( ) 代表函数
-
{ } 代表函数体
-
const ft = ()=>{} 代表把一个函数赋值给 ft
-
ft() 调用该函数
-
没有 arguments
-
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误
-
没有this指向 但是其this会指向上下文
-
目的是使代码更高雅简洁
# 4. 解构赋值
解构就是把数据结构进行`分解`,然后为定义的变量`赋值`。
// let a = [1,2,3] // 数组解构赋值 let [m1,m2,m3] = [1,2,3]
记得 对象解构 可以起别名
let obj = { name:'张三', age:18 } // 对象解构赋值 // let {name,age} = obj // console.log(name) // console.log(age) // : 后变量名 是起别名 分别是 变量名n 和 变量名a let {name:n,age:a} = obj
5. 剩余参数及展开运算符
5.1 剩余参数 (定收调打)
剩余参数允许我们将一个未知数量的参数表示为一个数组。
抛去已知的形参,获取未知的形参,结果以逗号分割
使用场景: 当函数的实参是动态的时候,无法判断出形参的个数,就可以使用剩余参数,从而拿到完整的参数
从上面的例子中我们发现参数 args 是一个数组。
5.2 展开运算符
把 数组 / 对象 外层的字面量去掉,如:
{}
和[]
,去掉字面量的部分,就是展开运算符的结果展开运算符和剩余参数的区别(面试) -
应用位置不同:
-
函数形参括号内的
...
--> 剩余参数 -
函数形参括号外的
...
--> 展开运算符
-
-
获取的结果不同:
-
剩余参数获取的是剩余的形参
-
展开运算符获取的是所有值
-
-
6. 可选链 及 短路运算
可选链 ?. 是一种 访问嵌套对象属性的防错误方法 。即使中间的属性不存在,也不会出现错误。 如果可选链 ?. 前面部分是 undefined 或者 null,它会停止运算并返回 undefined。
避免报错 需要 if判断或者短路运算避免
//es6 可选链
//不确定 obj 对象里的结构时
//规避 嵌套结构对象引用报错的问题
let obj = {
person:{
name:{
age:18
}
}
}
if(obj.person){
if(obj.person.name){
console.log(obj.person.name.age)
}
}
console.log(obj.person && obj.person.name && obj.person.name.age)
console.log(obj.person?.name?.age)
8. Set(集合)Map(字典)
Set 是 ES6 提供的一种数据结构,它和数组很像,但是它里面的数据是不可重复
的。 值-值
初始化 (注意 :1 和 ‘1’ 是不同类型数据)
const set1 = new Set([1, 2, 3, 4, 5, 5]); const set2 = new Set(['苹果','橘子','橘子']); console.log(set1); console.log(set2);
添加数据
const set1 = new Set([1, 2, 3, 4, 5,5]); set1.add(7);
删除数据
const set1 = new Set([1, 2, 3, 4, 5,5]); set1.delete(3);
包含数据
const set1 = new Set([1, 2, 3, 4, 5,5]); const res = set1.has(1); console.log(res);
遍历方法
const set1 = new Set([1, 2, 3, 4, 5,5]); set1.forEach((item,key)=>{})
清除所有数据
const set1 = new Set([1, 2, 3, 4, 5,5]); set1.clear();
共同点:集合、字典可以存储不重复的值 不同点:集合是以[值,值]的形式存储元素,字典是以[键,值]的形式存储 所以这一下让我们明白了,Map其实的主要用途也是用于存储数据的,相比于Object只提供“字符串—值”的对应,Map提供了“值—值”的对应。也就是说如果你需要“键值对”的数据结构,Map比Object更合适
初始化
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.get('Michael'); // 95
添加数据
var m = new Map() m.set('a',{age:10})
删除数据
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.delete('Bob')
读取数据
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.get('Bob')
包含数据
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.has('Bob')
清除所有数据
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.clear()
遍历方法
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.forEach((item,key)=>{})
9. 数组操作(面试)
9.1 合并数组 concat
let u1 = ['张三', '李四', '王五']; let u2 = ['张无忌', '赵敏', '周芷若']; let u3 = [...u1,...u2]; console.log(u3);
9.2 includes()
includes 用来判断该数组是否包含某个值,返回值是布尔值
9.3 find()
find 用来找到第一个符合条件的成员,没有找到返回 undefined
9.4 findIndex()
findIndex 用来找到第一个符合条件的成员的索引,没有的话返回 -1
16.1.1 every
基本概念
every是数组中的方法,只有当数组中所有的数据都满足条件的时候返回TRUE,有点像逻辑与运算符,一假则假的效果
代码展示
比如我们定义一个数组,判断数组中所有的数据是否都是偶数
let arr = [1,2,4,6,8,10,20,40,30]; let flag = arr.every(item=>{ return item%2==0; }) console.log(flag); //最后打印结果是false
let arr = [2,4,6,8,10,20,40,30]; let flag = arr.every(item=>{ return item%2==0; }) console.log(flag); //最后打印结果是false
效果如下所示:
16.1.2 some
基本概念
some是数组中的方法,数组中只要有一个条件满足就返回true,否则返回false,类似于js运算符中的逻辑或,一真则真
代码展示
比如我们有一个学生名单数据,我们想判断一下这个名单中是否有女生,可以使用some判断
let arr1 = [ { name: '张三', sex: "男" }, { name: '李四', sex: "男" }, { name: '王五', sex: "男" }, { name: '如花', sex: "女" }, ]; var isG = arr1.some(item => { return item.sex == "女"; }) console.log(isG); //打印结果为true
let arr1 = [ { name: '张三', sex: "男" }, { name: '李四', sex: "男" }, { name: '王五', sex: "男" }, { name: '如花', sex: "男" }, ]; var isG = arr1.some(item => { return item.sex == "女"; }) console.log(isG); //打印结果为false
效果如下所示:
16.1.3 reduce
概念
reduce() 函数将数组元素进行组合,例如求和,取最大值 第一个参数是指定函数,第二个参数是传递给函数的初始值;函数会返回一个简化后的值, arr.reduce((tmp,item,index)=>{},初始化的值) tmp 临时初始化的值,item循环对象,index索引值
代码展示
定义一个数组 arr = [2,4,6,8,10,20,40,30],我们来求他的和,常规方法如下所示:
let arr = [2,4,6,8,10,20,40,30]; let sum = 0; arr.forEach(item=>{ sum += item; }) console.log(sum);//打印结果120
使用reduce方法实现如下:
let arr = [2,4,6,8,10,20,40,30]; //tmp是每次累加的结果 item是每个内容 let result = arr.reduce((tmp,item)=>{return tmp+item}); console.log(result);//打印结果120
16.1.4 map
基本概念
map方法可以看成数组函数的映射而且是一一映射关系,我们使用的时候一般都使用return返回值,如果没有返回值,返回undefined。map单词本身就含有映射的含义
代码展示
定义一个数组,我们给数组中的每个数组计算平方后返回结果
let arr = [2, 4, 6, 8, 10, 20, 40, 30]; //item是每一项内容 let arr1 = arr.map(item=>{ return Math.pow(item,2); }) console.log(arr1);
效果展示如下所示:
16.1.5 filter
基本概念
filter函数可以看成是一个过滤函数,返回符合条件的元素的数组。 filter和map的区别:filter需要在循环的时候判断一下是true还是false,是true才会返回这个元素;map没有这个过程。
代码展示
我们有一个数组,存储的是一个用户列表,找出名字中有王的所有用户
let user = [ {name:'王小二',age:19,sex:"男"}, {name:'李四',age:33,sex:"男"}, {name:'王三',age:30,sex:"男"}, {name:'刘大脑袋',age:40,sex:"男"}, {name:'王西风',age:30,sex:"男"}, ]; let users = user.filter(item=>{ return item.name.indexOf("王")>-1; }) console.log(users);
代码展示如下所示:
10. 字符串扩展方法
10.1 startsWith() 和 endsWith()
startsWith()
表示该字符串参数是否在某个字符串头部
endsWith()
表示该字符串参数是否在某个字符串尾部
10.2 模板字符串(面试常考)
模板字符串是 ES6 新增加的创建字符串的方式
定义方式:反引号
定义
let country = `中国`;
解析变量
let country = `中国`; let message = `我爱你${country}`; console.log(message);
调用函数
const print = message=>message+",2022-04-25"; let message = `${print('我爱你中国')}`; console.log(message);
11.处理异步的方法
Promise (es6)
Promise有三种状态:pending(进行中)、resolved(成功)、rejected(失败)
失败状态: Promise 容器中 出错 或者 调用reject函数 都会进入到失败状态
原型方法:then() //成功状态执行的函数
catch() //失败状态执行的函数
finally () //不管成功还是失败状态 都会执行的函数
问题:
-
无法取消Promise,一旦新建它就会立即执行,无法中途取消。
-
如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
-
当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
方法:
all: // 多个promise 容器中的代码 都执行完毕时 才会触发then函数
let p1 = new Promise((res,rej)=>{ setTimeout(()=>{ res(1) },1000) }) let p2 = new Promise((res,rej)=>{ setTimeout(()=>{ res(2) },1000) }) let p3 = new Promise((res,rej)=>{ setTimeout(()=>{ res(3) },1000) }) let p = Promise.all([p1,p2,p3]) p.then(res=>{ console.log(res) }) // [1,2,3]
1.只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
2.只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
race:
let p1 = new Promise((res,rej)=>{ setTimeout(()=>{ res(1) },2000) }) let p2 = new Promise((res,rej)=>{ setTimeout(()=>{ res(2) },1000) }) let p3 = new Promise((res,rej)=>{ setTimeout(()=>{ res(3) },1000) }) Promise.race([p1,p2,p3]).then(res=>{ console.log(res) }) // 2
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
Generator (es6) 迭代器
Generator 是ES6引入的新语法,Generator是一个可以暂停和继续执行的函数。
Generator 基本语法包含两部分:函数名前要加一个星号;函数内部用 yield 关键字返回值。
1.与普通函数的区别:
普通函数:当使用return时,return以下部分将不会运行
2.Generator函数:使用yield+next() 可以返回多次值
因为return会阻止后面的代码运行,所以 Generator提供了yield,yield也是返回值,但是执行一次状态停在了第一个yield ,依次执行next方法,执行下一个yield状态。代码分段执行,一个yield分一段。上一个yield结束是下个状态的开始,下一个状态的结束再执行下一个yield。yield后面的是返回值。
// Generator 迭代器函数 function f1(){ setTimeout(()=>{ console.log(111) f.next() },3000) } function f2(){ setTimeout(()=>{ console.log(222) f.next() },2000) } function f3(){ setTimeout(()=>{ console.log(333) },1000) } function* fn(){ yield f1() yield f2() yield f3() } let f = fn() f.next() // 延迟3秒111 再延迟2秒222 再延迟1秒333
async/await (推荐使用) (是ES7提出的基于Promise的解决异步的最终方案。)
async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对async函数可以直接then,返回值就是then方法传入的函数。
async function fun0(){ return 1; } fun0().then(val=>{ console.log(val) // 1 }) async function fun1(){ return new Promise(function(resolve,reject){ resolve('Promise') }) } fun1().then(val => { console.log(val); //Promise })
await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待。
await 修饰的如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行;
如果不是Promise对象:把这个非promise的东西当做await表达式的结果。
async function fun(){ let a = await 1; let b = await new Promise((resolve,reject)=>{ setTimeout(function(){ resolve('setTimeout') },3000) }) let c = await function(){ return 'function' }() console.log(a,b,c) } fun(); // 3秒后输出: 1 "setTimeout" "function"
Async 是 Generator 的一个语法糖。
async 对应的是 * 。
await 对应的是 yield 。
async/await 自动进行了 Generator 的流程控制。
-
注意:若明确是当前函数内部需要异步转同步执行,再使用async。原因:babel会识别并将async编译成promise,造成编译后代码量增加。
优点:
使用async函数可以让代码简洁很多,不需要像Promise一样需要些then,不需要写匿名函数处理Promise的resolve值,也不需要定义多余的data变量,还避免了嵌套代码。
缺点:
错误处理:Async/Await 需要手动 try/catch 捕获错误。
async function fnAll(){ try{ obj.a = await p1 obj.b = await p2 obj.c = await p3 }catch(err){ console.log(err) } console.log(obj) } fnAll() Promise.all([p1,p2,p3]).then(res=>{ // console.log(res) obj.a = res[0] obj.b = res[1] obj.c = res[2] console.log(obj) }).catch(err=>{ console.log(err) })
12.Module 模块化
export default {} //默认导出 导出{}里的全全部
eport {}
import * from '路径'
import {} from '路径'
<script type="module"> import b from './lx.js' console.log(b) import {a,b,c} from './test.js' // console.log(a) console.log(b) // console.log(c) </script>