> For the complete documentation index, see [llms.txt](https://yyaozhibo.gitbook.io/qian-duan-xue-xi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yyaozhibo.gitbook.io/qian-duan-xue-xi/js/mian-xiang-dui-xiang-apply.md).

# 面向对象 - apply

`apply` 方法的作用与 call 方法类似，也是改变 this 指向，然后再调用该函数。唯一的区别就是，它接受一个数组作为函数执行时的参数，使用格式如下

```javascript
func.apply(thisValue, [arg1, arg2, ...])
```

`apply` 方法的第一个参数也是 `this` 所要指向的那个对象，如果设为 `null` 或 `undefined`，则等同于指定全局对象。第二个参数则是一个数组，该数组的所有成员一次作为参数，传入原函数。原函数的参数，在 `call` 方法中必须一个个添加，但是在 `apply` 方法中，必须以数组形式添加

```javascript
function f(x, y) {
  console.log(x + y)
}

f.call(null, 1, 1) // 2
f.apply(null, 1, 1) // 2
```

上面代码中，f 函数本来接受两个参数，使用 apply 方法以后，就变成可以接受一个数组作为参数

这一点利用，可以做一些有趣的应用

### 找出数组最大元素

`Javascript` 不提供找出数组最大元素的函数。结合使用 `apply` 方法和 `Math.max` 方法，就可以返回数组的最大元素

```javascript
var a = [10, 2, 4, 15, 9]
Math.max.apply(null, a) // 15
```

### 将数组的空元素变为 `undefined`&#x20;

&#x20;通过 `apply` 方法，利用 `Array` 构造函数将数组的空元素变成 `undefined`&#x20;

```javascript
Array.apply(null, ['a', ,'b'])
// ['a', undefined, 'b']
```

空元素与`undefined` 的差别在于，数组的 `forEach` 方法会跳过空元素，但是不会跳过 `undefined`。因此，遍历内部元素的时候，会得到不同的结果

```javascript
var a = ['a', , 'b']

function print(i) {
  console.log(i)
}

a.forEach(print)
// a
// b

Array.apply(null, a).forEach(print)
// a
// undefined
// b
```

### 转换类似数组的对象

另外，利用数组对象的 `slice` 方法，可以将一个类似数组的对象（比如 `arguments` 对象）转为真正的数组

```javascript
Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
```

上面代码的 `apply` 方法的参数都是对象，但是返回结果都是数组，这就起到了将对象转成数组的目的。从上面代码可以看到，这个方法起作用的前提是，被处理的对象必须有 `length` 属性，以及相对应的数字键

### 绑定回调函数的对象

前面的按钮点击时间的例子，可以改写如下

```javascript
var o = new Object()

o.f = function () {
  console.log(this === o)
}

var f = function () {
  o.f.apply(o)
  // 或者 o.f.call(o)
}

$('#button').on('click', f)
```

上面代码中，点击按钮以后，控制台将会显示 true。由于 apply 方法（或者 call 方法）不仅绑定函数执行时所在的对象，还会立即执行函数，因此不得不把绑定语句写在一个函数体内。
