# JavaScript中方法作为参数传递

> 在JavaScript中方法是一等公民，一等公民可以作为函数参数，可以作为函数返回值，也可以赋值给变量

## 问题来源

![image-20200811214756655](/Users/zhituxu/work/documents/docs/javascript/assets/image-20200811214756655.png)

## 以一个示例来理解一下

1. 首先我们写个定时器，规定从1开始打印，一次加1
```javascript
function countPlus() {
  let count = 0
  setInterval(() => {
    count++
    console.log(count)
  }, 1000)
}
countPlus()
```

运行 node demo.js，可查看结果: 1 2 3 4 ...

2. 有一个方法计算一个数+100

```javascript
function sumInfo(val) {
  console.log(val + 100)
}
sum(1)
```

运行后会输出: 101

3. 此时我们要调用countPlus的定时任务方法，每秒执行一次，但要求输出的每个值都加100，此时我们需要在countPlus中定义回调函数，将方法sumInfo作为参数传递给countPlus，代码如下：

```javascript
function countPlus(cb) {
  let count = 0
  setInterval(() => {
    count++
    cb(count)
  }, 1000)
}
// 以上代码一般为底层或API提供的代码，无法改变！以下为调用代码
function sumInfo(val) {
  console.log(val + 100)
}
countPlus(sumInfo)
// 上面这一行可以如下实现
countPlus((res) => {
  console.log(res + 100)
})
```

运行后会输出: 101 102 103 104 ...

4. 参照一下vue的实现，优化一下

**Vue中的钩子函数即是这样实现的，定义在某个特定的时候调用回调**

```javascript
const Vue = {
  addCountOne(cb) {
    let count = 0
    setInterval(() => {
      count++
      cb(count)
    }, 1000)
  }
}
//
Vue.addCountOne((res) => {
  console.log(res+100)
})
```

## 延伸一下

[Array.prototype.sort()](https://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)在对一些复杂数据结构进行排序时，可以使用**自定义的比较函数**作为参数：

```javascript
var employees = [
    { name: "Liu", age: 21 },
    { name: "Zhang", age: 37 },
    { name: "Wang", age: 45 },
    { name: "Li", age: 30 },
    { name: "zan", age: 55 },
    { name: "Xi", age: 37 }
];

// 员工按照年龄排序
employees.sort(function(a, b) {
    return a.age - b.age;
});

// 员工按照名字排序
employees.sort(function(a, b) {
    var nameA = a.name;
    var nameB = b.name;
    if (nameA < nameB) {
        return -1;
    }
    if (nameA > nameB) {
        return 1;
    }
    return 0;
});
```

> 这样写看起来没什么大不了的，但是对于JavaScript引擎来说就省事多了，因为它不需要为每一种数据类型去实现一个排序API，它只需要实现一个排序API就够了，至于数组元素大小怎么比较，交给用户去定义，用户如果非得说2大于1，那也不是不可以。
>
> 换句话说，如果Array.prototype.sort()只能实现简单数据（比如Number与String）的排序的话，那它就太弱了，正因为可以使用函数作为参数，使它的功能强大了很多。
>
> 顺便提一下，实现一个Array.prototype.sort()，可不是什么简单的事情，大家可以看看[V8是怎样实现数组排序的](https://link.zhihu.com/?target=https%3A//v8.dev/blog/array-sort)。

## 相关链接

[JavaScript深入浅出](https://blog.fundebug.com/tags/JavaScript深入浅出/)

[如何理解在 JavaScript 中 "函数是第一等公民" 这句话?](https://www.zhihu.com/question/67652709)

