this延伸,关于call、apply 和 bind的理解

181 阅读3分钟

this延伸,关于call、apply 和 bind的理解

在JavaScript里面,函数不仅仅是一行可执行代码,它们也是对象。这里callapplybind是三个非常重要的方法,它们关乎开发者精确控制函数内部的this上下文。

详细this讲解:揭秘 JavaScript 中的 this:谁在调用我?深入理解

.call()

  • 通过传递参数的方式,call()允许指定函数执行时的this上下文
  • call()被调用时,它会立即执行所引用的函数。
  • 这意味着一旦 call() 方法被执行,目标函数就会紧接着被调用,而不需要等待任何异步操作或事件循环的下一个周期。

示例:

var obj = {
  name: "Cherry",
  func1: function() {      
    console.log(this.name)
  },
  func2: function() {
    setTimeout(function() {
      this.func1()
    }.call(obj), 5000)  
  }
}

这里的打印并没有执行setTimeout定时器机制,而是立即执行了。 image.png

.bind()

  • bind 不会立即执行原函数,而是返回一个新的函数。
  • 可以提前绑定一些参数,即所谓的“部分应用”。
  • 新函数的 this 不会因为后续调用方式的不同而改变。

示例:

var obj = {
  name: "Cherry",
  func1: function() {      
    console.log(this.name)
  },
  func2: function() {
    setTimeout(function() {
      this.func1()
    }.bind(obj), 5000)  
  }
}

这里实现了延时执行的场景:

因为bind() 创建并返回一个新函数,其 this 永久绑定到指定对象,并在 setTimeout 的延迟后执行;而 call() 立即执行函数并临时绑定 this,不适用于延迟执行的场景。

.bind()与.call()的区别

var obj1 = {
  name: "Cherry",
}

function func1()  {      
    console.log(this.name)
}
func1.call(obj)
func1.bind(obj)

image.png

.apply()

用途apply 方法与 call 类似,与 call 一样,apply 也会立即执行函数。但它接受的是一个参数数组而不是一系列参数,所有参数都包含在一个数组中传递给目标函数。

示例:

var obj = {
   func:function(a,b){
        console.log(a+b)
    }
}
var a = obj.func 
// 将 `a.fn` 的值复制给变量 `b`,如果 `a.fn` 是一个对象或函数,
// 那么 `b` 和 `a.fn` 将引用同一个对象或函数实例
console.log(a.apply(a,[1,2]))

结果:

image.png

apply()、call()之间传递参数区别

  • apply(thisArg,[arg1,arg2,..])
    • thisArg参数,进行函数内部this的指向值。
    • [arg1,arg2,..] 参数做为数组或类数组对象,直接解析数组里面的每个元素,依次传递给目标函数。
  var obj = {
        func:function(a,arr){
            console.log(a)
            console.log(arr)
        }
    }
    var a = obj.func 
    // 将 `a.fn` 的值复制给变量 `b`,如果 `a.fn` 是一个对象或函数,
    // 那么 `b` 和 `a.fn` 将引用同一个对象或函数实例
    console.log(a.apply(a,[1,[1,2]]))

image.png

  • call(thisArg, arg1, arg2, ...)
    • thisArg参数,进行函数内部this的指向值。
    • arg1,arg2,... 参数一个个的,按顺序传递给目标函数。
   var obj = {
        func:function(a,b){
            console.log(a+b)
        }
    }
    var a = obj.func 
    // 将 `a.fn` 的值复制给变量 `b`,如果 `a.fn` 是一个对象或函数,
    // 那么 `b` 和 `a.fn` 将引用同一个对象或函数实例。
    console.log(a.call(a,1,2))
    console.log(a.call(a,[1,2]))

image.png 打印:1,2undefined

  • [1,2]作为一个整体传递给a,b没有传递值,定义为undefined。
  • 运用了连接运算符,a [1,2] + b undefined -> [1,2].tostring = '1,2' + String(undefined) = 'undefined' -> 1,2undefined

总结

在 JavaScript 中,callapplybind 方法都用于控制函数执行时的 this 上下文,但它们的行为有所不同:callapply 立即执行函数并分别以参数列表和参数数组的形式传递参数;而 bind 返回一个新函数,其 this 永久绑定到指定对象,适用于需要延迟执行或部分应用参数的场景。