JavaScript高级-this指向

111 阅读3分钟

一、this的绑定规则

  • 默认绑定
    • 独立函数调用
    • this指向window
    function foo() {
        console.log(this)
    }
    foo(); // window
    
  • 隐式绑定
    • 通过某个对象发起的函数调用
    • this指向该对象
    function foo() {
        console.log(this)
    }
    var obj = {
        name: "why",
        foo: foo
    }
    obj.foo(); // obj
    
  • 显示绑定
    • apply/call/bind
  • new绑定
    • 使用new关键字来调用函数
    • 会进行如下的操作
    /*
      1. 创建新的空对象
      2. 将this指向这个空对象
      3. 执行函数体中的代码
      4. 没有显示返回非空对象时,默认返回这个对象
    */
    
    function foo() {
      console.log("foo函数:", this);
    }
    
    new foo() // foo
    
  • 启示
    • 在函数调用时,JavaScript会默认给this绑定一个值
    • this的绑定和定义的位置没有关系
    • this的绑定和调用方式以及调用的位置有关系
    • this是在运行时被绑定的

二、apply/call/bind

function foo(name, age, height) {
  console.log("foo:", this);
  console.log("打印参数:", name, age, height);
}

// ()调用
foo("why", 18, 1.88) // window    why 18 1.88
  • apply
    • 第一个参数:绑定this
    • 第二个参数:传入额外的实参,以数组的形式
    foo.apply("apply", ["kobe", 30, 1.98]) // apply   kobe 30 1.88
    
  • call
    • 第一个参数:绑定this
    • 参数列表:后续的参数以多参数的形式来传递,会作为实参
    foo.call("call", "james", 25, 2.05) // call   james 25 2.05
    
  • bind
    • 总是显示的绑定到一个对象上
    var obj = { name: "why" }
    // 需求:调用foo时,总是绑定到obj对象身上(不希望obj对象身上有函数)
    // 1. bind函数的基本使用
    var bar1 = foo.bind(obj)
    // 2. bind函数的其他参数
    var bar2 = foo.bind(obj, "kobe", 18, 1.88)
    bar1()
    bar2()
    

三、this绑定优先级

  • 显示绑定的优先级高于隐式绑定
    • apply高于默认绑定
    • bind高于默认绑定
  • new绑定优先级高于隐式绑定
  • new/显式
    • new不可以和apply/call一起使用
    • new优先级高于bind
  • bind优先级高于apply/call

四、箭头函数的使用

  • 认识箭头函数
    • ES6之后增加的一种编写函数的方法,并且它比函数表达式更简洁
    • 箭头函数不会绑定this、arguments属性
    • 箭头函数不能作为构造函数来使用
    nums.forEach((item, index, arr) => {
    })
    
  • 箭头函数编写优化
    • 如果只有一个参数可以省略括号
    nums.forEach(item => {})
    
    • 如果函数执行体中只有一行代码,那么可以省略大括号
    nums.forEach(item => console.log(item))
    
    • 如果函数执行体中只有返回一个对象,那么需要给这个对象加上括号
    nums.forEach(item => ({name: "abc"}))
    
  • 箭头函数this
    • 箭头函数不绑定this对象
    • this引用会从上层引用中找到对应的this
    // 网络请求的工具函数
    function request(url, callbackFn) {
      var results = ["abc", "cba", "nba"]
      callbackFn()
    }
    
    // 实际操作的位置
    var obj = {
      names: [],
      network: function() {
        // 1. 早期的时候
        // network被obj调用,故这里的this指向obj
        var _this = this
        request("/names", function(res) {
          // 回调函数被默认调用,故这里的this指向window
          _this.names = [].concat(res)
        })
    
        // 2. 箭头函数写法
        request("/names", () => {
          // 箭头函数没有this,故会向上层作用域寻找
          // 上层作用域是network,this指向obj
          this.names = [].concat(res)
        })
      }
    }
    
    obj.network()
    console.log(obj);