简单了解 this 与 ES6

55 阅读8分钟

this 关键字

  • 概念: 每一个函数内部都有一个关键字 this
  • this 的值, 和 函数的调用有关, 与函数书写无关
  1. 一个普通的全局函数, 在正常调用的情况下, this === window
  2. 如果将函数放置到对象, 通过对象的语法去获取到并调用, 那么 this === 对象
  3. 如果将函数作为 事件处理函数, 那么触发的时候, 内部的 this 指向了 事件源
  4. 如果将函数作为定时器执行时的函数, 那么触发的时候, 内部的 this 指向了 全局对象 window
  • 全局定义函数

    function fn() {
        console.log(this)   // 这一行不能决定 this 的值, 想要知道他的值是什么, 需要调用函数的时候才能确定
    }
    
    // 1. 普通调用方式
    fn()    // this === window
    
  • 对象内部的函数

    // 2. 将函数 fn 赋值给 对象obj的c属性 fn 和 obj.c 是一个引用地址
    var obj = {
        a: 1,
        b: '我是对象obj的属性B',
        c: fn
    }
    obj.c() // this === obj     this 指向了 调用者
    
  • 定时器内部的函数

    // 3. 事件的方式触发
    var box = document.getElementById('box')
    box.onclick = fn    // this === box     this 指向了 事件源
    
  • 事件处理函数

    // 4. 倒计时器
    setTimeout(fn, 0)   // this === window
    setInterval(fn, 1000)   // this === window
    

call; apply; bind

  1. call()    可以帮助我们修改函数的 this 指向; 

    语法  函数.call(this指向谁, 参数1, 参数2, 参数3...)   第二个位置的参数, 会传递到函数中

    fn.call(obj, 300, 400)

  2. apply()  可以帮助我们修改函数的 this 指向;
      
    语法    函数.apply(this指向谁, [参数1, 参数2, 参数3])   第二个位置的数组内数据, 会传递到函数内部
    
    fn.apply(obj, [500, 600])

  3. bind()   可以帮助我们修改函数的 this 指向;
     
    语法    函数.bind(this指向谁, 参数1, 参数2, 参数3...)       第二个位置的参数开始, 会传递到函数中
    
    注意: bind 方法不会立即执行函数, 他会返回一个 内部 this 修改完毕的 新函数

ES5 与 ES6

  • ES6 其实就是 JS 发展过程中的 某一个 版本而已 那个版本的版本号叫做 ES6
  • 微信 在最初的时候, 是不具有 微信支付 随着版本的更新, 在某一个版本内推出了 微信支付
  • JS 在最初的时候, 是只有 var 关键可以声明变量 随着版本的更新, 在某一个版本内推出了 新的变量声明方式
  • JS 的更新 在 推出ES6 的时候, 这个版本推出的新东西比较多 所以后续程序员们为了方便记忆, 把 ES6 以后的版本 统称为 ES6+

let; const; var

ES6 新增两种变量声明的 方式

ES5 我们只能使用 var 声明变量

语法 和 var 一样

let 变量名 = 值

const 变量名 = 值

let/const 与 var 的差异

1. let/const 声明的变量 不允许出现重复的
    * 使用 var 声明变量的时候可以出现重复声明, 后一个值会覆盖前一个值
    * let/const 不允许
2. let/const 声明的变量没有变量提升
    * var 关键字声明的变量有变量提升, 值为 undefined
    * let/const 不允许
3. let/const 声明的变量 会受限于 所有的 {}
    * 也就是 使用 let/const 声明的变量 是块级作用域
    * var 声明的变量 只受限于 函数内部

let 与 const 的差异

1. let 声明的叫做变量(后续可以修改内部的值); 
    const 声明的叫做常量(后续不能修改内部的值, 也不能修改内部的引用地址)
2. 因为 let 后续可以修改变量的值, 所以他首次定义时, 可以不赋值;
    但是 const 声明的时常量, 后续不能重新修改他的值, 所以首次定义时, 必须赋值

箭头函数

  箭头函数就是对 ES5 普通函数的 写法上的一个优化

  箭头函数
      普通写法: (书写形参) => {书写函数调用时执行的代码}

  箭头函数的优化
      1. 箭头函数如果只有一个形参的时候, 可以不写前边的小括号(除此之外, 必写)
      2. 如果箭头函数的函数体, 只有一行代码, 那么可以省略 大括号(并且会默认将这行代码 return)

参数默认值

解构赋值

  • 解构对象

  • 解构数组

    /**
     *  解构赋值
     * 
     *      快速从数组或对象中取出成员的一种语法
    */
    
    // var arr = [1, 2]
    
    // ES5 拿到数组所有成员的方法
    // var num1 = arr[0]
    // var num2 = arr[1]
    // var num3 = arr[2]
    // console.log(num1, num2, num3)
    
    // ES6 解构赋值, 解构数组时, 赋值号左边必须写 中括号, 代表数组的解构赋值
    // let [num1, num2, num3] = arr
    // console.log(num1, num2, num3)
    
    var obj = {
        a: 11,
        b: 21,
        c: 31
    }
    
    // ES5 拿到对象所有成员的方法
    // var obj1 = obj.a
    // var obj2 = obj.b
    // var obj3 = obj.c
    
    // console.log(obj1, obj2, obj3)
    
    /**
     *  ES6 解构赋值, 解构对象时, 赋值号左边 必须写大括号, 代表对象的解构赋值
     * 
     *  大括号内部必须书写对象的 key
    */
    let { a, b, c } = obj
    console.log(a, b, c)
    

展开运算符

    /**
     *  展开(扩展)运算符
     * 
     *      语法: ...数组(对象)
     * 
     *      作用: 展开数组或者对象
     *              相当于把数组两侧包裹的中括号去掉
    */
    // var arr = [1, 2, 3]
    // console.log(arr)
    // console.log(...arr)

    // var obj = {
    //     a: 1,
    //     b: 2
    // }
    // console.log(obj)
    // // console.log(...obj)  // JS 不支持这样的写法

    // var obj1 = {
    //     ...obj,
    //     c: 3,
    //     d: 4
    // }
    // console.log(obj1)

    // var arr = [1, 2, 3]
    // var arr1 = [...arr, 100, 200, 300]
    // console.log(arr)
    // console.log(arr1)

    var arr = [1, 2, 3]
    function fn(a, b, c) {
        console.log(a, b, c)
    }
    fn(arr, 100, 200)

Map 和 Set

  • Set

      /**
       *  Map 和 Set
       * 
       *          es6 新推出的两种数据结构
       * 
       *      1. set  类似于 数组的 一种数据结构
       *              内部按照索引排序(但是不能通过索引取值)
       * 
       *          语法 let s = new Set([数据1, 数据2, 数据3])
       * 
       *          特点: 天生不支持重复数据
      */
    
      var arr = [1, 2, 3, 4, 5]
      console.log(arr)
      // console.log(arr[0]) // 数组允许使用索引获取到对应的值, set 不允许
    
    
      let s = new Set([3, 4, 5, 5, 5, 4, 4, 3])
      console.log('原始数据结构', s)
      // console.log(s[0])
    
    
      // 1. size (类似数组的 length); 作用: 获取到当前数据结构中 数据的数量
      // console.log(s.size)
    
      // 2. add 方法; 作用: 向当前数据结构中 新增数据
      // s.add(100)
      // s.add(5)
      // console.log('add 后的数据结构', s)
    
      // 3. has() 作用: 查询当前数据结构中是否拥有该数据; 找到的时候, 返回 true, 否则返回false
      // console.log(s.has(100))
      // console.log(s.has(5))
    
      // 4. delete(数据)   作用: 将当前数据结构中的 这个数据删掉
      // s.delete(5)
      // console.log(s)
    
      // 5. clear()   作用: 清空当前数据结构
      // s.clear()
      // console.log('清空后的数据结构 ', s)
    
      // 6. forEach   作用: 遍历数据结构, 拿到数据结构的每一项
      s.forEach(function (item, key, origin) {
          // set 数据结构是没有 key 所以 item 和 key 打印出来的值都一样
          console.log(item, key, origin)
      })
    
  • Map

      /**
       *  Map
       * 
       *      ES6 推出的一种数据结构
       * 
       *      和 set 一样, 也不支持重复数据
       * 
       *      类似于 对象的 一种数据结构
       *          但是 map 的 key 可以是任意类型的值
       * 
       *      语法: var m = new Map([key, value])
       * 
       *      在实际开发中, 我们使用 map 的场景一般为 想要将对象的 key 用于字符串之外的数据时使用
      */
      // var obj = {
      //     a: 1,
      //     b: 2
      // }
      // console.log(obj)
      // console.log(obj.a)  // 点语法, 将 a 当成一个字符串去对象中查找
      // console.log(obj["a"])   // 中括号语法, 去对象的key中查找一个 'a' 
    
      // var m = new Map([key, value])
    
      var arr = [1, 2, 3]
      var arr1 = [4, 5, 6]
      var m = new Map([[[500], [600]], [arr, arr1], ['arr123', arr1]])
      // console.log('原始数据结构: ', m)
    
    
      // 1. size  作用: 返回当前数据结构的 数据长度(多少个)
      // console.log(m.size)
    
      // 2. set() 作用: 向当前数据结构中, 新增数据
      m.set('newKey', [1, 2, 3, 4, 5])
      // console.log('set 新增数据后 的数据结构: ', m)
    
      // 3. get(key) 作用: 获取到指定key 对应的 value
      // console.log(m.get(arr))
      // console.log(m.get('newKey'))
    
      // 4. has(key)  作用: 查询数据结构中是否存在当前 key; 存在返回一个 true ,否则返回一个 false
      // console.log(m.has('12345'))
      // console.log(m.has('newKey'))
    
      // 5. delete    作用: 删除当前数据结构对应的 key
      // m.delete('newKey')
      // console.log(m)
    
      // 6. clear 作用: 清空当前数据结构
      // m.clear()
      // console.log(m)
    
      // 7. forEach
      m.forEach(function (item, key, origin) {
          /**
           *  item: 对应的 value
           *  key: 对应的 key
           *  origin: 对应的原始数据结构
          */
          console.log(item, key, origin)
      })
    

对象语法的简写

    /**
     *  对象语法的简写
     *      1. key 和 value 拼写一样
     *      2. 并且 value 写的是一个变量
     *  满足这两个条件的情况, 可以少写 其中一个
    */
    // console.log(window)
    // let name = 'QF666'
    // const obj = {
    //     name: name,
    //     age: 18,
    // }
    // const obj = {
    //     name,
    //     age: 18,
    // }
    // console.log(obj)
    /**
     *  obj === {
     *      name: 'QF666',
     *      age: 18
     *  }
    */

    let name = 'QF666'
    const obj = {
        name,
        age: 18,
        fn1: function () {
            console.log(1)
        },
        fn2() {
            console.log('222222')
        }
    }

    console.log(obj)
    
    obj.fn1()
    obj.fn2()

模块化开发

    // 1. 引入文件
    // import XXX from '文件路径'
    // 引入方式 1
    import headerFn from "./header.js"; // 这种引入方式, 只能引入 导出方式1(默认导出)
    // 引入方式 2
    import { obj, arr } from "./header.js"; // 这种引入方式, 只能引入 导出方式2

    import * as color from "./content.js";  // 将 content.js 内 导出的内容, 全部存放到 变量 color



    // 1. 向外暴露一些内容(导出)
    const fn = () => {
    console.log("我是功能模块1 的 fn 函数");
    };

    export default fn; // 默认导出(导出方式1)

    export const obj = {
    // 导出方式2
    name: "QF666",
    age: 18,
    };

    export const arr = [1, 2, 3, 4, 5];

    /**
    *  默认导出 一个 JS 文件 只能有一个
    *
    *  导出方式 2 可以有多个
    */