在一样平常 Coding 中,码农们一定少不了对数组的操纵,个中很经常运用的一个操纵就是对数组举行遍历,检察数组中的元素,然后一顿操纵猛如虎。
就好像我们去买生果,在一堆生果中,一个一个看优劣。这个好,嗯,要,放入袋中;这个不好,不要,放回;这个好,嗯,呀 …
在我熟悉的浩瀚计算机言语中,如 Java、Python、JS,都有对 forEach 的完成,本日临时简朴地说说在 JavaScript 中 forEach。
进修或研讨言语供应的函数 API,平常都邑有这么几步:
- 看函数原型,邃晓参数
- 撸!实战,不停考证
- 深切源码,看优异的代码,完成体式格局
- 进修头脑,形式
代码很主要,但头脑、认知更主要!
那末,不多说,先来看看 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);
}
}
固然,代码只给了关键性代码,内里少了许多合理性推断,特别处置惩罚等。但思绪就在那了,更完美的代码待人人来补充,一同交换。
原创不简朴,码字不容易,点个赞,行不行 !