Você já deve saber o que é e para que serve o método forEach
, mas já se perguntou como ele funciona de fato?
[1,2,3,,5].forEach((n) => console.log(n))
// 1
// 2
// 3
// 5
De Acordo com a Especificação
Para responder essa pergunta, vamos consultar a especificação oficial do ECMAScript. Resumidamente:
- forEach tem dois parâmetros:
- callback
- thisArg
- callback deve ser uma função com três parâmetros:
- o valor do elemento,
- o índice do elemento,
- o objeto iterado
- O método converte o valor de this em um objeto. (this é o nosso array iterado)
- Obtém o comprimento do objeto como um número.
- Verifica se o callback é uma função.
- Itera de k = 0 até k < len:
- Para cada índice existente (k in O), executa callback.call(thisArg, O[k], k, O).
A especificação existe para que a implementação em diferentes motores JS (ex: V8, SpiderMonkey, JScript, etc) seja padronizada.
Implementação em JavaScript
Podemos fazer nossa própria implementação para melhor visualização:
function forEach(callback, thisArg) {
if (!this) {
throw new TypeError('"this" is null or undefined');
}
// 1. Let O be ? ToObject(this value).
const O = Object(this);
// 2. Let len be ? LengthOfArrayLike(O)
const len = O.length;
// 3. If IsCallable(callback) is false, throw a TypeError exception.
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 4. Let k be 0.
let k = 0;
// 5. Repeat, while k < len,
while (k < len) {
// a. Let Pk be ! ToString(𝔽(k)).
const Pk = k.toString();
// b. Let kPresent be ? HasProperty(O, Pk).
const kPresent = Pk in O;
// c. If kPresent is true, then
if (kPresent) {
// i. Let kValue be ? Get(O, Pk).
const kValue = O[Pk];
// ii. Perform ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
callback.call(thisArg, kValue, k, O);
}
// d. Set k to k + 1.
k++;
}
// 6. Return undefined.
return undefined;
}
Implementação no V8
Apesar de ser possível replicar em JavaScript, a especificação é destinada a motores JS. É possível consultar a implementação pelo motor do Chrome por exemplo: https://github.com/v8/v8/blob/main/src/builtins/array-foreach.tq#L38-L66