引言
在JavaScript中,函数调用的上下文(即this的值)是一个非常重要的概念。为了在不同的上下文中调用函数,JavaScript提供了三种主要的方法:apply、call和bind。这些方法不仅允许我们指定函数调用的上下文,还在参数传递方面有不同的特点和用途。接下来我将通过一段实例代码详细说明三者不同的传参方式以及各自适用场景。
实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var a = {
name: '刘大壮',
// call 和 apply 区别
// apply 一次性给,以数组的形式
// call 一个个给 call(thisBinder,a,b,c,......)
fn: function(a, b) {
console.log(this.name)
// a [1,2] + undefined
// 如果两边不都是数字 (加不了+变字符串连接符)
console.log(a + b)
}
}
var b = a.fn;// b 是一个普通函数
// 指定this
// 立即执行
// 参数
console.log(b.apply(a, [1, 2]))
console.log(b.call(a, [1,2]))//错误传参
console.log(b.call(a,1,2))
console.log(b.bind(a,1,2)())
</script>
</body>
</html>
重点关注这段代码的输出情况,如图所示
console.log(b.apply(a, [1, 2]))
console.log(b.call(a, [1,2]))
console.log(b.call(a,1,2))
console.log(b.bind(a,1,2)())
除了 console.log(b.call(a, [1,2]))以外其他都拿到了正常结果,好下面将介绍三者的传参方式以及为什么这局代码会输出1,2undefined。
三者传参特点介绍以及适用场景:
apply 方法
apply 方法允许你调用一个函数,并为其指定一个 this 值和一个参数数组。这意味着你可以将一组参数作为一个数组传递给函数。
-
适用情况:
- 当你已经有一个参数数组,并且希望将这个数组作为函数的参数列表时,使用
apply是最合适的。 - 例如,如果你从另一个函数或数据源获取了一个参数数组,并且需要将这个数组作为参数传递给目标函数,
apply可以方便地将数组元素展开作为函数的参数。 - 它在处理动态参数列表(存储在数组中)时非常有用。
- 当你已经有一个参数数组,并且希望将这个数组作为函数的参数列表时,使用
call 方法
call 方法与 apply 类似,也是用来调用一个函数并为其指定 this 值。然而,call 方法在传递参数时不是使用数组,而是将参数逐一列出。
-
适用情况:
- 当你明确知道要传递的参数数量,并且这些参数是独立的、可列举的,使用
call会更加方便。 - 例如,当调用一个函数,并且你想指定
this的值,同时传递几个明确的参数时,call是一个简洁的选择。 - 它适合于参数数量较少且明确的情况,因为你可以直接将参数逐个列出。
- 当你明确知道要传递的参数数量,并且这些参数是独立的、可列举的,使用
bind 方法
bind 方法创建一个新的函数,当这个新函数被调用时,它的 this 值被指定为 bind 的第一个参数,其余参数将作为新函数调用时的初始参数。
-
适用情况:
- 当你需要创建一个新函数,该函数的
this值和部分参数已经预先确定,并且可以在后续调用时添加更多参数,使用bind。 - 常用于创建回调函数,确保
this指向特定对象,同时部分参数已经确定,后续调用时可以添加额外参数。 - 它不会立即调用函数,而是返回一个新函数,该函数的
this绑定和部分参数已经设置好。
- 当你需要创建一个新函数,该函数的
为什么console.log(b.call(a, [1,2]))会输出:1,2undefined?
在原代码中,由于 fn 函数接收的第一个参数是 [1,2],第二个参数是 undefined,当执行 console.log(a + b) 时:
[1,2]会被转换为字符串"1,2",因为数组的toString()方法会将数组元素用逗号连接起来。undefined会被转换为字符串"undefined"。- 所以最终结果是
"1,2undefined",因为+运算符在这种情况下会将它们作为字符串拼接起来。
总结
apply方法以数组的形式一次性传递所有参数,适用于参数以数组或类数组对象形式存在的情况。call方法逐一传递参数,适用于明确知道要传递的参数时。bind方法创建一个新的函数,该函数的this值被绑定,并且可以预设一些初始参数,不会立即调用函数。
理解这些方法的区别和用途,可以帮助我们在不同的场景下选择合适的方法来调用函数,从而更灵活地控制函数的上下文和参数传递。