四. ES6 1-6(P120-P126)

98 阅读11分钟

四. ES6

  • 我们所说的 ES5 和 ES6 其实就是在 js 语法的发展过程中的一个版本而已
  • ECMAScript 就是 js 的语法
    • 以前的版本没有某些功能
    • 在 ES5 这个版本的时候增加了一些功能
    • 在 ES6 这个版本的时候增加了一些功能
  • 因为浏览器是浏览器厂商生产的
    • ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能
    • 这个过程是需要时间的
    • 所以到现在,基本上大部分浏览器都可以比较完善的支持了
    • 只不过有些浏览器还是不能全部支持
    • 这就出现了兼容性问题
    • 所以我们写代码的时候就要考虑哪些方法是 ES5 或者 ES6 的,看看是不是浏览器都支持

1.ES6定义变量

let 和 const 关键字

1.let变量

2.const常量

  • 我们以前都是使用 var 关键字来声明变量的

  • 在 ES6 的时候,多了两个关键字 letconst,也是用来声明变量的

  • 只不过和 var 有一些区别

letconst 的相同点

1. letconst 不允许重复声明变量
 ```javascript
 // 使用 var 的时候重复声明变量是没问题的,只不过就是后面会把前面覆盖掉
 var num = 100
 var num = 200
 ```

 ```javascript
 // 使用 let 重复声明变量的时候就会报错了
 let num = 100
 let num = 200 // 这里就会报错了
 ```

 ```javascript
 // 使用 const 重复声明变量的时候就会报错
 const num = 100
 const num = 200 // 这里就会报错了
 ```
2. letconst 声明的变量不会在预解析的时候解析(也就是没有变量提升)
 ```javascript
 // 因为预解析(变量提升)的原因,在前面是有这个变量的,只不过没有赋值
 console.log(num) // undefined
 var num = 100
 ```

 ```javascript
 // 因为 let 不会进行预解析(变量提升),所以直接报错了
 console.log(num) // undefined
 let num = 100
 ```

 ```javascript
 // 因为 const 不会进行预解析(变量提升),所以直接报错了
 console.log(num) // undefined
 const num = 100
 ```
3. letconst 声明的变量会被所有代码块限制作用范围
 ```javascript
 // var 声明的变量只有函数能限制其作用域,其他的不能限制
 if (true) {
   var num = 100
 }
 console.log(num) // 100
 ```

 ```javascript
 // let 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...)
 if (true) {
   let num = 100
   console.log(num) // 100
 }
 console.log(num) // 报错
 ```

 ```javascript
 // const 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...)
 if (true) {
   const num = 100
   console.log(num) // 100
 }
 console.log(num) // 报错
 ```

letconst 的区别

1. let 声明的变量的值可以改变,const 声明的变量的值不可以改变
 ```javascript
 let num = 100
 num = 200
 console.log(num) // 200
 ```

 ```javascript
 const num = 100
 num = 200 // 这里就会报错了,因为 const 声明的变量值不可以改变(我们也叫做常量)
 ```
2. let 声明的时候可以不赋值,const 声明的时候必须赋值
 ```javascript
 let num
 num = 100
 console.log(num) // 100
 ```

 ```javascript
 const num // 这里就会报错了,因为 const 声明的时候必须赋值
 ```
<script>
        // console.log(a)
        // var a = 100

        // function test(){
        //     var a = 100
        // }


        // ES6新关键字  let变量 const常量

        /*
          与var区别

          1. 必须先定义再使用
          2. 变量重名
          3. 块级作用域 {}  避免跟外面变量互相打扰
        */

        //1. 必须先定义再使用
        // console.log(a)    
        // let a = 100
        // console.log(a)


        //2. 变量重名
        // let name = "kerwin"
        // let name = "xiaomoing"

        // console.log(name)

        //3. 块级作用域 {}
        // if(true){
        //     let i = 100
        //     console.log(i)  //100
        // }

        // console.log(i)  //报错


        // let 变量
        // let name = "kerwin"
        // name = "xiaoming"

        // const 常量  赋值完后无法改变

        const obj = {
            name: "kerwin"
        }

        // obj.name = "xiaoming"  //没有覆盖 栈和堆
        // obj = {name:"xiaoming"}  //重新覆盖 报错
        console.log(obj)


        // let a 
        //const a 
    </script>

案例:块级作用域

原来var定义

for(var i=0; i<oHeaderItems.length; i++){
            //自定义属性
            oHeaderItems[i].dataset.index = i
            oHeaderItems[i].onclick = handler
        }
        // console.log(i)

        function handler(){
            // console.log(this.dataset.index)
            var index = this.dataset.index
            for(var m=0;m<oHeaderItems.length; m++){
                oHeaderItems[m].classList.remove("active")
                oBoxItems[m].classList.remove("active")
            }

            oHeaderItems[index].classList.add("active")
            oBoxItems[index].classList.add("active")
        }

用let定义

for (let i = 0; i < oHeaderItems.length; i++) {
            //自定义属性
            // oHeaderItems[i].dataset.index = i
            oHeaderItems[i].onclick = function () {
                console.log(i)
                // console.log(this.dataset.index)
                var index = i
                for (var m = 0; m < oHeaderItems.length; m++) {
                    oHeaderItems[m].classList.remove("active")
                    oBoxItems[m].classList.remove("active")
                }

                oHeaderItems[index].classList.add("active")
                oBoxItems[index].classList.add("active")
            }
        }

2.箭头函数

  1. (只有一个形参的时候)可以省略

  2. {} 可以省略 只有一句代码 或 只有返回值的时候,省略return

  3. 没有arguments 无法拿到arguments

  4. 箭头函数没有this, 箭头函数this是父级作用域的,不再是谁调用它就指向谁了

2-1 箭头函数语法

  • 箭头函数是 ES6 里面一个简写函数的语法方式

  • 重点: 箭头函数只能简写函数表达式,不能简写声明式函数

    function fn() {} // 不能简写
    const fun = function () {} // 可以简写
    const obj = {
      fn: function () {} // 可以简写
    }
    
  • 语法: (函数的行参) => { 函数体内要执行的代码 }

    const fn = function (a, b) {
      console.log(a)
      console.log(b)
    }
    // 可以使用箭头函数写成
    const fun = (a, b) => {
      console.log(a)
      console.log(b)
    }
    
    const obj = {
      fn: function (a, b) {
        console.log(a)
        console.log(b)
      }
    }
    // 可以使用箭头函数写成
    const obj2 = {
      fn: (a, b) => {
        console.log(a)
        console.log(b)
      }
    }
    

2-2 箭头函数的特殊性

1. 函数的行参只有一个的时候可以不写 () 其余情况必须写
const obj = {
  fn: () => {
    console.log('没有参数,必须写小括号')
  },
  fn2: a => {
    console.log('一个行参,可以不写小括号')
  },
  fn3: (a, b) => {
    console.log('两个或两个以上参数,必须写小括号')
  }
}
2. 函数体只有一行代码的时候,可以不写 {} ,并且会自动 return
const obj = {
  fn: a => {
    return a + 10
  },
  fun: a => a + 10
}

console.log(fn(10)) // 20
console.log(fun(10)) // 20
3. 箭头函数内部没有 arguments 这个参数集合
const obj = {
  fn: function () {
    console.log(arguments)
  },
  fun: () => {
    console.log(arguments)
  }
}
obj.fn(1, 2, 3) // 会打印一个伪数组 [1, 2, 3]
obj.fun(1, 2, 3) // 会直接报错
4. 箭头函数内部没有 this,箭头函数的 this 是上下文的 this
// 在箭头函数定义的位置往上数,这一行是可以打印出 this 的
// 因为这里的 this 是 window
// 所以箭头函数内部的 this 就是 window
const obj = {
  fn: function () {
    console.log(this)
  },
  // 这个位置是箭头函数的上一行,但是不能打印出 this
  fun: () => {
    // 箭头函数内部的 this 是书写箭头函数的上一行一个可以打印出 this 的位置
    console.log(this)
  }
}

obj.fn()
obj.fun()
  • 按照我们之前的 this 指向来判断,两个都应该指向 obj
  • 但是 fun 因为是箭头函数,所以 this 不指向 obj,而是指向 fun 的外层,就是 window
5. 函数传递参数的时候的默认值
  • 我们在定义函数的时候,有的时候需要一个默认值出现

  • 就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数

    function fn(a) {
      a = a || 10
      console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 在 ES6 中我们可以直接把默认值写在函数的行参位置
    function fn(a = 10) {
      console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 这个默认值的方式箭头函数也可以使用
    const fn = (a = 10) => {
      console.log(a)
    }
    fn()   // 不传递参数的时候,函数内部的 a 就是 10
    fn(20) // 传递了参数 20 的时候,函数内部的 a 就是 20
    
    • 注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()

代码总结

<body>
    <input type="text" id="mytext">
    <script>
        // var test1 = function(){
        //     console.log("11111")
        // }


        //箭头函数形式 () => {}
        // var test2 = () => {
        //     console.log(2222)
        // }

        // test1()
        // test2()

        /*
         1. (只有一个形参的时候)可以省略
         2. {} 可以省略 只有一句代码 或 只有返回值的时候,省略return

         3. 没有arguments 无法拿到arguments

         4. 箭头函数没有this, 
            箭头函数this是父级作用域的,不再是谁调用它就指向谁了
        */


        //1. (只有一个形参的时候)可以省略()
        // var test = (a,b) => {
        //     console.log(111,a,b)
        // }

        // test("kerwin",100)

        // 2. {} 可以省略 只有一句代码 或 只有返回值的时候,省略return
        /* var test = a => {
            return 100*a
        }
        */
        //省略后
        // var test = a => 100*a
        // console.log(test(10))



        // var list = ["aaa","bbb","ccc"]

        /*
        var newlist = list.map(item=>{
            reture `<li>${item}</li>`
        })
        */
        //省略后
        // var newlist = list.map(item=>`<li>${item}</li>`)
        // console.log(newlist.join(""))


        /*
        var test = ()=>{
            console.log("111111")
        }
        */
        //省略后
        // var test = ()=>console.log("111111")
        // test()


        //两个{}
        /*
        var test = () => {
            return{
                name:"kerwin"
            }
         }
        */
        //省略后 要加()
        // var test = () => ({
        //         name:"kerwin"
        // })

        // console.log(test())


        //3. 没有arguments 无法拿到arguments
        /*var text = function(a,b,c){
            console.log(a,b,c)
        }
        text(1,2,3)
        */
        //去掉形参
        // var test = () => {
        //     // console.log(a,b,c)

        //     console.log(arguments[0],arguments[1],arguments[2])

        //     // console.log(Array.from(arguments))
        // }
        // test(1,2,3)


        //4. 箭头函数没有this, 
        //    箭头函数this是父级作用域的
        
        //普通函数
        // mytext.oninput = function(){
        //     var that = this
        //     setTimeout(function(){
        //         console.log(that.value)
        //     },1000)
        // }

        //箭头函数 this是父级作用域的,不再是谁调用它就指向谁了
        mytext.oninput = function(){
            // var that = this
            setTimeout(()=>{
                console.log(this.value)
            },1000)
        }

        //函数的默认参数,少传参数就走默认
        // function test(a=1,b=2){
        //     return a+b
        // }

        var test = (a=1,b=2)=>{
            return a+b
        }
        console.log(test(10,20))
        console.log(test())
    </script>
</body>

3 解构赋值

  • 解构赋值,就是快速的从对象或者数组中取出成员的一个语法方式

3-1 解构对象

  • 快速的从对象中获取成员

    // ES5 的方法向得到对象中的成员
    const obj = {
      name: 'Jack',
      age: 18,
      gender: '男'
    }
    
    let name = obj.name
    let age = obj.age
    let gender = obj.gender
    
    // 解构赋值的方式从对象中获取成员
    const obj = {
      name: 'Jack',
      age: 18,
      gender: '男'
    }
    
    // 前面的 {} 表示我要从 obj 这个对象中获取成员了
    // name age gender 都得是 obj 中有的成员
    // obj 必须是一个对象
    let { name, age, gender } = obj
    

3-2 解构数组

  • 快速的从数组中获取成员

    // ES5 的方式从数组中获取成员
    const arr = ['Jack', 'Rose', 'Tom']
    let a = arr[0]
    let b = arr[1]
    let c = arr[2]
    
    // 使用解构赋值的方式从数组中获取成员
    const arr = ['Jack', 'Rose', 'Tom']
    
    // 前面的 [] 表示要从 arr 这个数组中获取成员了
    // a b c 分别对应这数组中的索引 0 1 2
    // arr 必须是一个数组
    let [a, b, c] = arr
    

注意

{} 是专门解构对象使用的
[] 是专门解构数组使用的
  • 不能混用
<script>
        // 快速的从对象和数组中获取里面的成员

        var arr = ["xiaoming","teichui","shanzhen"]
        // arr[arr.length-1]

        let [x,y,z] = arr

        console.log(x,y,z)

        var a = 10
        var b = 20

        var [b,a] = [a,b]

        console.log(a,b)

        var arr2 = [1,2,[3,4,[5]]]//多维度数组 数组嵌套

        // console.log(arr2[2][2][0])  //5
        var [q,w,[e,r,[t]]] = arr2

        console.log(t) //5


        // var obj = {
        //     name:"kerwin",
        //     age:100,
        //     location:"dalian"
        // }

        // let {name,age:myage,location:mylocation} = obj
        // document.write(name)
        // document.write(myage)
        // // document.write(location)
        // document.write(mylocation)


        var obj2 = {
            name:"kerwin",
            age:100,
            location:{
                province:"liaoning",
                city:"dalian"
            },
            hobby:[111,222,333]
        }

        var {
            name,
            age,
            location:{
                province,
                city
            },
            hobby:[m,n,k]
        } = obj2

        console.log(name,age,province,city,m,n,k)  //kerwin 100 liaoning dalian 111 222 333
    </script>

4. ES6的对象简写

可以省略:以及:后的

<body>
    <input type="text" id="myusername">
    <input type="password" id="mypassword">
    <button id="mybtn">login</button>
    <script>
        mybtn.onclick = function () {
            let username = myusername.value
            let password = mypassword.value

            console.log(username,password)

            var obj = {
        //省略前username:username,
            //  password:password

                username,
                password
            }

            console.log("发给后端的结构",obj)
        }


        var obj = {
            a:1,
            //省略前getName:function(){
            getName(){
                console.log(this.a)
            }
        }

        obj.getName()
    </script>
</body>

5. 展开运算符

  • ES6 里面号新添加了一个运算符 ... ,叫做展开运算符

作用是把数组展开

let arr = [1, 2, 3, 4, 5]
console.log(...arr) // 1 2 3 4 5

合并数组的时候可以使用

let arr = [1, 2, 3, 4]
let arr2 = [...arr, 5]
console.log(arr2) //[1,2,3,4,5]

也可以合并对象使用

let obj = {
  name: 'Jack',
  age: 18
}
let obj2 = {
  ...obj,
  gender: '男'
}
console.log(obj2)

在函数传递参数的时候也可以使用

let arr = [1, 2, 3]
function fn(a, b, c) {
  console.log(a)
  console.log(b)
  console.log(c)
}
fn(...arr)
// 等价于 fn(1, 2, 3)

代码总结

<body>
    <ul>
        <li>1111</li>
        <li>1111</li>
        <li>1111</li>
        <li>1111</li>
        <li>1111</li>
    </ul>

    <h1>修改</h1>

    <input type="text" id="myusername">
    <input type="number" id="myage">
    <button id="btn">修改</button>
    <div id="box"></div>
    <script>
        // ... 展开数组
        // var a = [1,2,3]
        // var b = [4,5,6]
        // // console.log(a.concat(b))
        // var c = [...a,...b]
        // console.log(c) //[1,2,3,4,5,6]

        //...复制
        // var a = [1,2,3]
        // var b = [...a]
        // b[0] = "kerwin" //[1,2,3] ['kerwin',2,3]

        // console.log(a,b)

        //...参数-实参-形参

        // var test = function(a,b,...arr){
        //     console.log(arr)
        // }

        // test(1,2,3,4,5)  //[3,4,5]
        // var arr = [1,2,3]
        // var test = function(a,b,c){
        //     console.log(a,b,c)
        // }

        // test(...arr) //1 2 3

        // var arr = [1,2,3,5,3,6,4,8]
        // var res = Math.max(...arr)  //8

        // console.log(res)


        //...伪数组转换

        // function test(){
        //     var arr = [...arguments]
        //     console.log(arr)
        // }
        // test(1,2,3,4,5)
            
        // var oli = document.querySelectorAll("li")
        // // console.log(oli.filter)
        // var oliarr = [...oli] 
        // console.log(oliarr.filter) [li,li,li,li,li]


        //...对象

        // var obj1 = {
        //     name:"kerwin",
        //     age:100
        // }
        // var obj2 = {
        //     name:"tiechui",
        //     location:"dalian"
        // }

        // var obj = {
        //     ...obj1,
        //     ...obj2
        // }
        // console.log(obj) // name:'tiechui',age:100,location:'dalian'


        var obj = {
            name:"kerwin",
            age:100,
            location:"dalian",
            id:"214589498387584375"
        }


        function render({name,age,location}){
            // console.log(obj)
            // var {name,age,location} = obj
            box.innerHTML = `name:${name},age:${age},localtion:${location}`
        }

        render(obj)

        btn.onclick = function(){
            //最新的name和age
            var name = myusername.value || obj.name
            var age = myage.value || obj.age

            var newobj = {
                ...obj,
                name,
                age
                //...展开后,有修改的就给它放进来,在后面写
            }

            console.log(newobj)

            //亲给后端

            //重新渲染页面

            render(newobj)
        }
    </script>

6.模版字符串

  • ES5 中我们表示字符串的时候使用 '' 或者 ""

  • 在 ES6 中,我们还有一个东西可以表示字符串,就是 ``(反引号)

    let str = `hello world`
    console.log(typeof str) // string
    
  • 和单引号还有双引号的区别

    1. 反引号可以换行书写

      // 单引号或者双引号不能换行,换行就会报错了
      let str = 'hello world' 
      
      // 下面这个就报错了
      let str2 = 'hello 
      world'
      
      let str = `
      	hello
      	world
      `
      
      console.log(str) // 是可以使用的
      
    2. 反引号可以直接在字符串里面拼接变量

      // ES5 需要字符串拼接变量的时候
      let num = 100
      let str = 'hello' + num + 'world' + num
      console.log(str) // hello100world100
      
      // 直接写在字符串里面不好使
      let str2 = 'hellonumworldnum'
      console.log(str2) // hellonumworldnum
      
      // 模版字符串拼接变量
      let num = 100
      let str = `hello${num}world${num}`
      console.log(str) // hello100world100
      
      • `` 里面的 ${} 就是用来书写变量的位置

7.ES6模块化语法

//导出
export {
    //A1:A1,对象简写
    A1,
    A2,
    test,
    A_A
}


//C中引入A和B
//自己用自己引
import { A_A } from './A.js'
import { B_B } from './B.js'

function C() {
    A_A()
    B_B()

    console.log("CC")
}

// export {
//     C
// }
//默认导出,只能导出1个
export default C 
<script type="module">
        import CCCC from './module/C.js'
        import {A1,A2,test as A_test} from './module/A.js'
        //as重命名
        import {B1,B2,test as B_test} from './module/B.js'
        
        A1()
        A2()
        A_test()
        B_test()

        // console.log(C)
        CCCC()
    </script>