在JavaScript中,`call` 和 `apply` 是两种非常重要的函数调用方式,它们都是`Function.prototype`对象上的方法,因此所有的函数实例都可以使用。这两种方法的主要作用是允许我们在不改变函数本身的情况下,动态地改变函数内部`this`的指向,从而能够借用其他对象的方法。
`call` 方法的基本语法是 `func.call(thisArg, arg1, arg2, ..., argN)`。这里的`thisArg`是想要绑定到函数内部`this`的值,`arg1, arg2, ..., argN`则是传递给函数的参数。例如在例子中:
```javascript
function A() {
this.getName = function(xx) {
return xx;
}
}
function B() {}
var a = new A();
console.log(a.getName('i am A')); // 输出 "i am A"
var b = new B();
console.log(a.getName.call(b, 'i am B')); // 输出 "i am B"
```
在这个例子中,`a.getName.call(b, 'i am B')` 使用了`call`方法,使得原本属于`a`的`getName`方法被`b`调用,`this`的值被设置为`b`,所以输出的是 "i am B"。
另一方面,`apply` 方法的语法是 `func.apply(thisArg, [argsArray])`。这里`argsArray`是一个数组或者类数组对象,它的元素将作为单独的参数传递给函数。例如:
```javascript
function A() {
this.sun = function(a, b) {
return a + b;
}
}
function B() {}
var a = new A();
console.log(a.sun(1, 2)); // 输出 3
var b = new B();
console.log(a.sun.call(b, 2, 2)); // 输出 4
console.log(a.sun.apply(b, [3, 3])); // 输出 6
```
在这个例子中,`a.sun.apply(b, [3, 3])` 使用`apply`将数组`[3, 3]`中的元素作为参数传递给`sun`方法,实现了相同的效果。
`call`和`apply`在实际开发中的一个常见应用场景是处理类似数组的对象,如`document.getElementsByTagName`返回的结果。由于这个结果不是真正的数组,不能直接使用数组的方法,但我们可以通过`Array.prototype.slice.call`将它转换为真正的数组,然后就可以使用数组的方法了:
```javascript
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
// 现在domNodes可以使用数组的所有方法
```
`call`和`apply`提供了灵活性,让我们能够在不同对象之间共享和调用方法,同时改变`this`的指向,这对于面向对象编程和处理复杂数据结构时非常有用。理解并熟练掌握这两种方法对于JavaScript开发者来说至关重要。