📜  函数.prototype.apply 和函数.prototype.call 的区别(1)

📅  最后修改于: 2023-12-03 15:36:50             🧑  作者: Mango

函数.prototype.apply 和函数.prototype.call 的区别

在 JavaScript 中,函数是一等公民,也是一种对象。因此,每个函数都有自己的属性和方法。在函数中,我们可以通过两个方法 Function.prototype.apply()Function.prototype.call() 来改变函数的 this 指向。这两个方法的作用非常相似,但有一些细微的区别。

语法

它们的语法都很相似,都是在函数对象上调用:

func.apply(thisArg, [argsArray]);
func.call(thisArg, arg1, arg2, ...);

其中:

  • func:要调用的函数对象。
  • thisArg:在调用函数时要使用的 this 值。可以为任何值。
  • argsArray:一个数组或类数组对象,包含了调用函数时要用到的参数。如果不需要参数,则可以省略该参数。
  • arg1, arg2:依次列出的参数列表。如果不需要参数,则可以省略该参数。
区别

参数传递方式的不同

使用 apply()call() 方法可以实现将一个对象指定为函数的 this 值,并且传递一些参数给该函数,使函数能够正常运行。

apply() 方法接收一个数组或类数组对象作为参数,这个数组中存放要传入的参数。而 call() 方法则是接受若干个参数,每个参数之间用逗号分隔。

let obj = {
  name: '张三'
}

function sayHello(msg) {
  console.log(`${msg},${this.name}`)
}

sayHello.call(obj, '你好')
sayHello.apply(obj, ['你好'])

上面的例子中,sayHello() 函数被调用两次,输出结果都一样。

参数的传递方式对性能的影响

由于传递参数的方式不同, call() 方法略优于 apply() 方法。调用时传递的参数不同,这会导致执行效率的不同。

例如,在 someFunction.apply(null, args) 中,实际上是先将 args 这个数组展开之后再传递给函数。这样会导致一些性能问题,每次调用函数时都要展开数组。

而在 someFunction.call(null, ...args) 中,... 运算符会将 args 数组中的元素直接作为参数传递给函数。这样就可以节约展开数组的操作时间。

总结

总的来说,call()apply() 是非常有用的方法,它们能够帮助我们在合适的时机改变函数的 this 值,并且传递一些参数给函数。

如果传递的参数是数组或者对象等类数组对象时,建议使用 apply() 方法,如果传递的是若干个参数,则可以使用 call() 方法。

在实际使用中应当取决于具体的需求,不要过分追求性能优化而影响代码的可读性和可维护性。