ES6的一些语法

236 阅读7分钟

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