JavaScript中call()方法的context参数工作原理及_.each实现疑问
你已经掌握的person.fullName.call(myObject)逻辑,和iteratee.call(context, collection[i], i, collection)的逻辑是完全一致的:call方法的第一个参数永远是指定函数执行时的this指向,这里的context就是给迭代器函数iteratee绑定内部this的目标对象。
举个实际使用的例子就能快速理解
假设你有一个带状态的对象,需要在遍历集合的过程中操作这个对象的属性:
// 我们要绑定的上下文对象 const counter = { count: 0, add: function (num) { this.count += num } } // 待遍历的数组 const arr = [1, 2, 3, 4] // 调用你实现的_.each,把context指定为上面的counter对象 _.each(arr, function (item) { // 这里的this就会指向counter,而不是全局对象 this.add(item) }, counter) console.log(counter.count) // 输出10,刚好是1+2+3+4的结果
如果调用_.each时不传第三个context参数,那么iteratee执行时的this就遵循原生call的规则:非严格模式下指向全局对象,严格模式下为undefined,符合Underscore的可选参数设计。
对应你代码里的参数说明
iteratee.call(context, collection[i], i, collection)四个参数的作用分别是:
- 第一位
context:调用_.each时传入的可选上下文,绑定到iteratee的this上 - 第二位
collection[i]:当前遍历到的元素值 - 第三位
i:当前遍历到的索引(数组)或键名(对象) - 第四位
collection:原集合本身
后面三个参数就是Underscore官方约定的,迭代器函数接收的三个入参。
和你已经理解的call示例对应
你之前写的示例:
person.fullName.call(myObject);
和这里的写法只是多了几个传参而已,对应关系完全一致:
| 你之前的示例 | _.each里的写法 | 作用 |
|---|---|---|
| person.fullName | iteratee | 要执行的函数 |
| myObject | context | 函数执行时this的指向对象 |
| 无后续参数 | collection[i], i, collection | 传给执行函数的入参 |
这个可选context参数的设计,就是为了方便开发者在需要绑定迭代函数内部this的场景下,不用手动做bind或者额外保存this变量,直接传入上下文即可。
内容的提问来源于stack exchange,提问作者Detla888
相关产品推荐
相关产品推荐

