Js中的 forEach 源码

更新日期: 2019-06-02 阅读: 3.5k 标签: 源码

在日常 Coding 中,码农们肯定少不了对数组的操作,其中很常用的一个操作就是对数组进行遍历,查看数组中的元素,然后一顿操作猛如虎。

就好像我们去买水果,在一堆水果中,一个一个看好坏。这个好,嗯,要,放入袋中;这个不好,不要,放回;这个好,嗯,呀 …

在我认识的众多计算机语言中,如 Java、Python、JS,都有对 forEach 的实现,今天暂且简单地说说在 JavaScript 中 forEach。

学习或研究语言提供的函数 api,一般都会有这么几步:

  1. 看函数原型,理解参数
  2. 撸!实战,不断验证
  3. 深入源码,看优秀的代码,实现方式
  4. 学习思想,模式

代码很重要,但思维、认知更重要!

那么,不多说,先来看看 forEach 函数的原型:

/**
* currentValue : 遍历到的当前元素
* index : 当前元素的索引值 (可选)
* arr : 当前元素所属的数组对象,即 array (可选)
* thisValue : 当执行回调函数时用作 this 的值(参考对象) (可选)
* 
* 返回值: undefined
*/
1. array.forEach(function(currentValue, index, arr), thisArg);
2. arr.forEach(callback[, thisArg]);

这里有两种函数原型的表达方式,第一种看起来稍微清楚明白点,第二种偏高大上,Linux 上很常见。看个人所接触的语言及习惯,哪种适合自己,哪种能让自己更容易理解、明白就看哪种就好,不必纠结!


适合自己的才是最好的!

其中 currentValue 就是遍历到的当前元素,拿买苹果作例子,我们从一堆苹果中,一个个挑,而 currentValue 就是我们从水果堆中拿到的那个苹果;

index 是当前元素的索引,也就是我们手中的苹果是拿过的苹果中是第几个,比如这个是拿的我第二个,那 index 就是 1。为什么是 1 不是 2 呢 ?因为计算机语言是从 0 开始的,这是一个哲学问题;

arr 是当前元素所属的数组对象,说白了就是那一堆苹果。

而 thisArg,就很难解释了。还是看例子吧,说千遍,不如做一步,自己敲一下,运行后,理解可能更深。

后面三个参数都是可选的,可有可无,估计他们很想哭。


来个栗子:

var array1 = ['a', 'b', 'c'];
var array2 = ['1','2','3'];
array1.forEach(function(currentValue, index, arr) {
    console.log(currentValue, index, arr, this);
},array2);

# 输出
// 如果给 forEach() 传递了 thisArg 参数,当调用时,它将被传给 callback 函数,作为它的 this 值。否则,将会传入 undefined 作为它的 this 值
> "a" 0 ["a", "b", "c"] ["1", "2", "3"] 
> "b" 1 ["a", "b", "c"] ["1", "2", "3"]
> "c" 2 ["a", "b", "c"] ["1", "2", "3"]

我们看到,数组的每一个元素及他们对应的索引被依次输入,而 arr 就是它自己,而 this 则是 array2,是我们在调用 forEach 时传进去的,在里面被当作 this 了。


源码呢 ?

说到这,JavaScript 不像 Java 一样,它提供的函数的源码并不是用本身自己这种语言编写的,而是用 C 或 C++ 写的。这些函数,其实只是一种对外公开的规范,就像是向开发提供的接口一样。所以严格讲,JavaScript 不是一门语言,而是一套规范,一套 API。
这与很多语言有着很大的不同。

对同一个函数,或者说同一个 API,也有多种不同的方式实现,因此,我们很难像 Java 一样查看 forEach 的源码,一个函数,在同一个版本,源码一致。

我们只能通过一些公开的参考一些浏览器内核公开代码。


例如,mozilla 的 forEach 源码:

/* ES5 15.4.4.18. */
function ArrayForEach(callbackfn/*, thisArg*/) {
  var O = ToObject(this);
  var len = ToLength(O.length);
 if (arguments.length === 0)
   ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.forEach");
  if (!IsCallable(callbackfn))
   ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
  var T = arguments.length > 1 ? arguments[1] : void 0;

  for (var k = 0; k < len; k++) {
   if (k in O) {
   callContentFunction(callbackfn, T, O[k], k, O);
   }
  }
  return void 0;
}

那我们能不能根据实际用途效果,参照前面的源码,自己用 JavaScript 手写一个 forEach 呢 ?
当然,可以!

我这里写了两种不同的 forEach 的实现,如果你有更好的方式,欢迎贴代码交流。


1.使用 call 方式

Array.prototype.forEach = function(callback,thisArg){
  var len = this.length;
  for(var i = 0; i < len; i++){
   // callback(this[i], i, this);
   callback.call(thisArg,this[i], i, this);
  }
}


2.使用 bind 方式

Array.prototype.forEach = function(callback,thisArg){
 var len = this.length;
 callback = callback.bind(thisArg);
 for(var i = 0; i < len; i++){
  callback(this[i], i, this);
 }
}

当然,代码只给了关键性代码,里面少了很多合理性判断,特殊处理等。

原文来自:https://segmentfault.com/a/1190000019361055


本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/3510

相关推荐

star-history源码阅读:Github的stargazers接口与分页机制

Github官方提供了一系列REST API(现在有向graphql上迁移的趋势),通过REST API,可以获得许多Github上的信息,以此为基础,我们可以构建各式各样的APP,star-history这个项目也是这样建立起来的,Github虽然没有提供直接查看项目star历史的功能

微信小程序代码源码案例大全

克隆项目代码到本地(git应该都要会哈,现在源码几乎都会放github上,会git才方便,不会的可以自学一下哦,不会的也没关系,gitHub上也提供直接下载的链接);打开微信开发者工具;

亲测源码,等大量源码免费下载-龙腾源码网

超多源码在龙腾源码网随处可见,高质量的源码给您带来不一样的感觉,无论是搭建还是询问

Vue 3 源码开放了

于2019年10月5日凌晨,尤雨溪在微博宣布 Vue 3.0 的源码开放了。目前依然是 pre-alpha 状态,但主要的架构改进、优化和新功能都已经完成,剩下的主要是完成一些 Vue 2 现有功能的移植

Node 集群源码初探

随着这些模块逐渐完善, Nodejs 在服务端的使用场景也越来越丰富,如果你仅仅是因为JS 这个后缀而注意到它的话, 那么我希望你能暂停脚步,好好了解一下这门年轻的语言,相信它会给你带来惊喜

vue源码解析:nextTick

nextTick的使用:vue中dom的更像并不是实时的,当数据改变后,vue会把渲染watcher添加到异步队列,异步执行,同步代码执行完成后再统一修改dom,我们看下面的代码。

React源码解析之ExpirationTime

在React中,为防止某个update因为优先级的原因一直被打断而未能执行。React会设置一个ExpirationTime,当时间到了ExpirationTime的时候,如果某个update还未执行的话,React将会强制执行该update,这就是ExpirationTime的作用。

React源码解析之ReactDOM.render()

React更新的方式有三种:(1)ReactDOM.render() || hydrate(ReactDOMServer渲染)(2)setState(3)forceUpdate;接下来,我们就来看下ReactDOM.render()源码

扒开V8引擎的源码,我找到了你们想要的前端算法

算法对于前端工程师来说总有一层神秘色彩,这篇文章通过解读V8源码,带你探索 Array.prototype.sort 函数下的算法实现。来,先把你用过的和听说过的排序算法都列出来:

Vue源码之实例方法

在 Vue 内部,有一段这样的代码:上面5个函数的作用是在Vue的原型上面挂载方法。initMixin 函数;可以看到在 initMixin 方法中,实现了一系列的初始化操作,包括生命周期流程以及响应式系统流程的启动

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!