# 面向对象 - 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 方法）不仅绑定函数执行时所在的对象，还会立即执行函数，因此不得不把绑定语句写在一个函数体内。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yyaozhibo.gitbook.io/qian-duan-xue-xi/js/mian-xiang-dui-xiang-apply.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
