ES6全称:ECMAScript-2015, 是2015年推出的全新的js语法.
语法的更新其实就是在原来的语法基础上, 新增了几个新的语法, 而不是把之前学的js语法给完全替换覆盖.
ES6语法
1.let 与const
声明变量关键字
ES5声明变量var
- 有变量预解析: 变量的声明会提升到当前作用域最顶端
- 没有块级作用域
变量预解析:
// (1)预解析 : 变量的声明会提升到当前作用域最顶端
console.log(num)
var num = 10
/* 相当于了下面代码
var num // 变量预解析
console.log( num ) // undefined
num = 10
*/
没有块级作用域:
//(2)没有块级作用域 :
for (var i = 1; i <= 5; i++) {}
console.log(i) // 打印 6
ES6声明变量 let 和 const
- 没有变量预解析
- 有块级作用域
let与const区别:
- let : 变量。 可以修改
- const : 常量。 不可以修改 且只可以声明的时候赋值一次,之后无法修改
- 实际开发中, 只要不修改的变量都用const,需要改的时候用let
2.对象解构:
解构语法:取出对象的属性值 赋值 给 变量
const { uname, age } = {uname: '平安', age: 19}
等价于const uname = {uname: '平安', age: 19}.uname
等价于const age = {uname: '平安', age: 19}.age
要求属性名和变量名必须一致才可以(等号左边的uname为变量,等号右边的uname为属性)
对象解构的变量名 可以重新改名, 语法为:旧变量名: 新变量名
例如:
const { uname: username, age } = {uname: '平安', age: 19}
console.log(username)结果为: 平安
console.log(uname) 结果为:uname is not defined
解构语法:取出变量的属性 赋值 给 对象
//2. 取出变量的属性 赋值 给 对象
let username = 'admin'
let password = '123456'
// //ES5
// let p = {
// username:username,
// password:password
// }
//ES6
let p = {
username,//username:username
password,
say() {
console.log(111);
},//say: function () { }
}
console.log(p);
如果变量名与属性名不一致,必须写成下面这样。(在属性名相同的情况下,)
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
console.log(f); // 'hello'
console.log(l); // 'world'
如果变量名与属性名一致, 可以这么写(在属性名相同的情况下,) 解构
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
console.log(foo); // "aaa"
console.log(bar); // "bbb"
这实际上说明,对象的解构赋值是下面形式的简写
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再把属性值赋给对应的变量。真正被赋值的是后者,而不是前者。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // "aaa"
console.log(foo); // error: foo is not defined
上面代码中,foo是匹配的模式(可以理解为属性名),baz才是变量。真正被赋值的是变量baz,而不是模式foo。由于这里的变量名和属性名不同,所以不能简写.
多级对象解构:
const pig = {
name: '平安',
age: 19,
family: {
mother: 'ai',
father: 'jia',
brother: 'ren'
}
}
// 多级对象解构
const { age: age, family: { mother, father, brother } } = pig
console.log(age);
console.log(family);
4.数组解构
数组解构是将数组的单元值快速批量赋值个一系列变量的简洁语法.
(1) 取出数组元素的值,赋值给变量
// 普通数组
let arr = [10, 20, 30, 40]
// 批量声明变量n1, n2, n3, n4
// 同时将数组单元值10, 20, 30, 40 依次赋值给变量[n1, n2, n3, n4
let [n1, n2, n3, n4] = arr
console.log(n1, n2, n3, n4); //10 20 30 40
(2) 取出变量的值, 赋值给数组元素
let num1 = 1
let num2 = 2
let num3 = 3
let newArr = [num1, num2, num3]
console.log((newArr)); //[1, 2, 3]
多维数组解构:
const [a, [b, c]] = ['陈平安', ['宁姚', '阮秀']]
console.log(a); // 陈平安
console.log(b); // 宁姚
console.log(c); // 阮秀
5.函数解构
<script>
/* 函数参数解构: 当函数参数是对象类型,就可以对形参进行解构 */
//传参本质: 实参给形参赋值
function fn({ name, age, gender }) { //等价于{ name, age, gender} = { name: '陈平安', age: 20, gender: '男'}
// 对象解构
console.log(name, age, gender);
}
// 实参
fn({ name: '陈平安', age: 20, gender: '男' })
// 函数参数结构流程推理
// let obj = {name: '陈平安', age: 20, gender: '男'}
// let {name, age, gender} = obj
// 上面两行代码其实可以简写成一行
// let { name, age, gender} = { name: '陈平安', age: 20, gender: '男' }
</script>
6.箭头函数
1.箭头函数 : 相当于function函数的简写
(1) 把function改成箭头 => (2) 把形参() 写在箭头 左边
2.箭头函数语法注意点
2.1 如果箭头函数只有一个形参,则可以省略小括号
2.2 如果箭头函数的 函数体 只有一行代码,则可以省略大括号。 (此时必须省略return)
下面的代码说明了2.1和2.2中的话
let fn = function(a){
return a*2
} 可以改写为
let fn = a => a*2
7.展开运算符...
它的作用是在调用函数、数组构造时将数组表达式或字符串在语法层面进行展开;构建字面量的对象时以键值对的形式进行展开。对象字面量是一个逗号分隔列表的零个或多个键值对的集合,这些键值对由一对大括号“{}”括起来。字面量指的是能够使用简单结构和符号创建对象的表达式。比如字符串字面量,使用一个双引号来创建字符串对象,而不需要完整的调用 new String() 语句,字面量其实就是指变量的常数值.
<script>
let obj = {
name: '陈平安',
age: 19,
love: '宁姚'
}
let objs = { ...obj }
console.log(objs);
// 打印结果 {name: '陈平安', age: 19, love: '宁姚'}
</script>
7.1 用于数组
以数组为例, 先创建一个数组
const a = [1, 2, 3],
b = [4,5,6];
console.log(...a); //1 2 3
// 实时上上面的语句只是在语法层面展开了数组a 让a中的每一个元素作为log函数的参数
赋值有一个数组:
const c = [...a] // [1,2,3]
拼接数组:const d = [...a,...b] // [1,2,3,4,5,6]
字符串转为数组:console.log([...'vue']) // ['v', 'u', 'e']
数组拷贝:
const arr1 = [1,2,3,4];
const arr2 = [...arr1]; // [1,2,3,4]
arr2.push(5,6); // 此时arr2 [1,2,3,4,5,6] arr1的结果不变
const arr3 = [[1,2,3],[4,5,6]];
const arr4 = [...arr3]; // [[1,2,3],[4,5,6]] 不会继续往下遍历;
arr4.pop().push(0);
// 执行后 arr4 [[1,2,3]]
// arr3 [[1,2,3],[4,5,6,0]]
从以上结果我们可以看出 展开运算符只遍历展开数组的第一层(浅拷贝)。 展开的结果如果是引用类型则不继续向下遍历
7.2 用于对象的拷贝与合并
const obj1 = {
name: '陈平安',
age: 20,
love: '宁姚'
}
const obj2 = {
name: 'lala',
age: 19,
student: '裴钱'
}
// 使用展开运算符拷贝对象(浅拷贝)
const copyObj = { ...obj1 }; // { name:'陈平安' , age:20, love: '宁姚'}
使用展开运算符合并对象:
let obj3 = { ...obj2, ...obj1 }
打印:age: 20 love: "宁姚" name: "陈平安" student: "裴钱"
使用展开运算符进行新对象构造 本质上是讲原有对象中的所有 可枚举 属性拷贝到新对象中, 注意: 合并后的新对象拥有全部属性, 相同的属性,后者会覆盖前者.
8.rest参数(剩余参数):
语法为...变量名:用于获取函数的多余参数,这样就不需要使用arguments对象了,返回的是一个真数组, 这个特性可以让我们在一些特定环境更方便的去处理参数.
let fn = (...values) => {
console.log(values);
}
fn(1,3,5); // 打印 [1,3,5]
注意: rest参数后不能有其他参数(rest必须是最后一个参数)
let fn = (a, ...values, b) =>{} // 报错
注意: 在数组或函数参数中使用展开语法时, 只能用于 可迭代对象
let love = {username:'cxp'};
let arr = [...love]; // TypeError: lover is not iterable
9.数据类型Set
得到的结果是集合, 并且这个集合里不能存储重复元素
应用: 数组去重
let newArr = [...new Set(数组)]
let arr = [10, 20, 30, 50, 60, 78, 20, 50, 60, 678]
//console.log(arr);
let set = new Set(arr)
console.log(set) // Set(7) {10, 20, 30, 50, 60, 78, 678}
let newArr = [...set]
console.log(newArr); // [10, 20, 30, 50, 60, 88, 90]
数组迭代
1.数组map方法
作用: 映射数组,得到映射之后的新数组
需求: 全场商品打5折 (映射: 两个数组元素一一对应的)
原数组: [10,20,30,40,50]
映射数组: [5,10,15,20,25]
特点:
回调函数执行次数 == 数组长度
回调函数内部的return作用: return 新数组元素
map方法的最终返回值: *返回映射之后的新数组
let arr = [10, 20, 30]
let newArr = arr.map(item => item * 2)
console.log(newArr); // [5,10,15]
2.数组filter方法
作用: 筛选数组,得到满足筛选条件的新数组
需求: 根据价格筛选商品
特点:
回调函数执行次数 == 数组长度
回调函数内部的return作用:
return true : 满足筛选条件,会放入新数组中
return false : 不满足筛选条件,不会放入新数组中
最终返回值:
*返回满足筛选条件的新数组
let arr = [188, 98, 278, 600, 800]
let newArr = arr.filter(item => item <= 300)
console.log(newArr); // [188,98,278]
3.数组forEach方法
作用: 遍历数组 注意: 她还可以遍历伪数组, *相当于for循环
特点:
回调执行次数 == 数组长度
回调函数return作用: 无
最终自身返回值: 无
let arr = [187, 98, 288, 827, 600 ]
arr.forEach((item, index) => {
console.log(item, index);
})
4.数组some方法
作用: 判断数组中有没有满足条件的元素
应用: 非空判断(判断有没有空) (逻辑或||)
特点:
回调函数执行次数 != 数组长度
回调函数内部的return作用
return true : 循环结束. 找到满足的元素,并且some的结果也是true
return false : 循环继续, 没有找到满足条件的元素,如果所有的元素遍历结束还是false,最终some的结果也为false
最终返回值:
*true: 有满足条件的元素
*false: 没有满足条件的元素
// 需求: 判断数组中有没有奇数
let arr = [188, 98, 278, 600, 800]
// 完整写法
let res = arr.some((item, index) => {
if (item % 2 == 1) {
return true
} else {
return false
}
})
console.log(res);// 打印 false
// 另一种写法
let arr = [188, 98, 278, 600, 800]
let res = arr.some(item => item % 2 == 1)
console.log(res); // 打印 false
5.数组every方法
作用: 判断数组中有没有满足条件的元素
应用: 全选(判断是否全部选中) (逻辑与&&)
特点:
回调函数执行次数 != 数组长度
回调函数内部的return作用:
return true : 循环继续. 满足条件,如果所有的元素都是true,最终every的结果也是true
return false : 循环结束, 不满足条件,此时every的结果也是false
最终返回值:
*true: 所有元素都满足条件
*false: 有元素不满足条件
// 需求: 判断数组是不是都是偶数
let arr = [188, 98, 278, 600, 800]
// // 完整写法
let res = arr.every((item, index) => {
if (item % 2 == 0) {
return true
} else {
return false
}
}) // true
// 另外一种写法
let arr = [188, 98, 278, 600, 800]
let res = arr.some(item => item % 2 == 1)
console.log(res); //true
6.数组findIndex方法
作用: 查找元素的下标
* 数组的findIndex与indexOf异同点:
相同点:功能一致,都是查找元素下标。 有则返回下标,无则返回固定值-1
不同点:应用场景不同
indexOf : 查找数组中的元素都是值类型
findIndex : 查找数组中的元素都是引用类型
特点:
回调函数执行次数 != 数组长度
回调函数内部的return作用:
* return true : 循环结束。 找到了,此时返回值就是下标
* return false : 循环继续。 没找到,循环继续。 如果所有元素全部遍历还是没找到,最终结果就是-1
最终自身返回值:
* 下标: 找到元素
* -1: 没有该元素
//需求:找名字为陈平安的人在哪里
let arr = [
{ name: '陈平安', age: 19 },
{ name: '宁姚', age: 18 },
{ name: '阮秀', age: 17 },
]
let res = arr.findIndex(item => item.name == '陈平安')
console.log(res); // 打印 0
678.数组reduce方法
作用: 给每一个元素执行一次回调
场景: 数组求和
reduce的参数介绍:
/* 第一个参数: 回调函数
(sum,item,index)=>{
sum: 累加和. 本次循环的sum值就是上一次回调的返回值
item: 数组元素
index: 数组下标
}
第二个参数: 初始化 一般传0(下面代码后的0就是第二个参数.)
* 默认情况下reduce会从1下标开始, 如果遇到空数组就会报错
*/
返回值: 最后一次sum 的结果.
let arr = [10, 90, 78]
let res = arr.reduce((sum, item, index) => {
//console.log(sum, item, index)
return sum + item
}, 0)
console.log(res); // 打印 178