this、call、apply、bind解读

时间:2021-2-20 作者:admin

this

在深入了解this前,我们要知道this在调用函数时能够控制使用不同的上下文环境,同时this永远指向最后调用它的对象,在EcmaScript中已经有效的规避的this容易产生的错误,但是在我们阅读某个框架源码的时候,还是要深入了解下this


理解this指向

我们通过例子去理解this指向的问题。

例如我们拥有一个USER的对象,并且通过点号的形式进行调用。

const USER = {
  name: 'Taylor',
  age: 34,
  greet() {
    console.log(`name: ${USER.name}`)
    console.log(`name: ${this.name}`)
  }
}

USER.greet()

// 输出结果:
// name: Taylor
// name: Taylor

可以看到我们在调用方法的时候相当于把this指向了USER对象。

const STUDENT = {
  name: 'Taylor',
  age: 12,
  greet() {
    console.log(`name: ${STUDENT.name}`)
    console.log(`name: ${this.name}`)
  },
  mother: {
    name: 'Swift',
    age: 35,
    greet() {
      console.log(`name: ${STUDENT.mother.name}`)
      console.log(`name: ${this.name}`)
    }
  }
}

STUDENT.greet()
STUDENT.mother.greet()

// 输出结果:
// name: Taylor
// name: Taylor
// name: Swift
// name: Swift

改变this指向

能够改变this指向的操作有:

  • 箭头函数

  • 函数内部使用_this = this

  • apply

  • call

  • bind

  • new一个对象

箭头函数
const OBJ = {
  name: 'Taylor',
  time1: function() {
    setTimeout(function() {
      console.log(`name: ${this.name}`) // name: windowName
    }, 0)
  },
  time2: function() {
    setTimeout(() => {
      console.log(`name: ${this.name}`) // name: Taylor
    }, 0)
  }
}

OBJ.time1()
OBJ.time2()
函数内部使用_this = this
const OBJ = {
  name: 'Taylor',
  time1: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: windowName
    }, 0)
  },
  time2: function() {
    let _this = this
    setTimeout(function() {
      console.log(`NAME: ${_this.name}`) // name: Taylor
    }, 0)
  }
}

OBJ.time1()
OBJ.time2()
apply
const OBJ = {
  name: 'Taylor',
  time1: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: windowName
    }, 0)
  },
  time2: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: Taylor
    }.apply(OBJ), 0)
  }
}

OBJ.time1()
OBJ.time2()
call
const OBJ = {
  name: 'Taylor',
  time1: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: windowName
    }, 0)
  },
  time2: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: Taylor
    }.call(OBJ), 0)
  }
}

OBJ.time1()
OBJ.time2()
bind
const OBJ = {
  name: 'Taylor',
  time1: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: windowName
    }, 0)
  },
  time2: function() {
    setTimeout(function() {
      console.log(`NAME: ${this.name}`) // name: Taylor
    }.bind(OBJ)(), 0)
  }
}

OBJ.time1()
OBJ.time2()
new绑定
function User (name, age) {
  this.name = name
  this.age = age
}

const func = new User('Taylor', 27)

apply和call的区别

  • apply接受一个包含多个参数的数组
  • call接受多个参数
apply传参
const OBJ ={
  fn: function(a, b) {
    console.log(a + b) // 3
  }
}

let func = OBJ.fn;
func.apply(OBJ, [1,2])
call传参
const OBJ ={
  fn: function(a, b) {
    console.log(a + b) // 3
  }
}

let func = OBJ.fn;
func.call(OBJ, 1, 2)

bind和apply、call的区别

bind方法创建一个新的函数, 当bind被调用时,将其this指向为bind的第一个参数,在调用新函数时提供剩余参数序列。

const OBJ ={
  fn: function(a, b) {
    console.log(a + b) // 3
  }
}

let func = OBJ.fn;
func.bind(OBJ, 1, 2)()
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。