Bind thisArg in the array callback methods of dynamic arrays

forEach, map, filter, some, every, find, findIndex, findLast,
findLastIndex and flatMap on a dynamic array, and through
Array.prototype.<method>.call on a native array, called the callback
without its thisArg, so `this` in the callback was not the second
argument. These methods now bind `this` to the thisArg, or undefined
when there is none, once per call, around all of the method's callbacks.
This commit is contained in:
Chris Tate
2026-10-26 10:19:57 -05:00
parent a59df23c71
commit 928c30e908
2 changed files with 164 additions and 101 deletions
@@ -20,3 +20,46 @@ console.log(words.join(","), Array.prototype.includes.call(words, "a"));
const records: { id: number }[] = [{ id: 1 }, { id: 2 }, { id: 3 }];
Array.prototype.copyWithin.call(records, 1, 0, 1);
console.log(records.map((r) => r.id).join(","), records[0] === records[1]);
// The callback methods bind `this` to their thisArg, for native arrays
// through .call and for dynamic arrays called directly.
type Scale = { k: number; seen: number[] };
const scale: Scale = { k: 10, seen: [] };
const values: number[] = [1, 2, 3, 4];
Array.prototype.forEach.call(values, function (this: Scale, v: number) {
this.seen.push(v);
}, scale);
console.log(scale.seen.join(","));
console.log(Array.prototype.map.call(values, function (this: Scale, v: number) {
return v * this.k;
}, scale).join(","));
console.log(Array.prototype.filter.call(values, function (this: Scale, v: number) {
return v * this.k > 15;
}, scale).join(","));
console.log(
Array.prototype.some.call(values, function (this: Scale, v: number) { return v === this.k / 5; }, scale),
Array.prototype.every.call(values, function (this: Scale, v: number) { return v < this.k; }, scale),
Array.prototype.find.call(values, function (this: Scale, v: number) { return v * this.k === 30; }, scale),
Array.prototype.findIndex.call(values, function (this: Scale, v: number) { return v * this.k === 30; }, scale),
Array.prototype.findLast.call(values, function (this: Scale, v: number) { return v * this.k < 30; }, scale),
Array.prototype.findLastIndex.call(values, function (this: Scale, v: number) { return v * this.k < 30; }, scale),
);
console.log(Array.prototype.flatMap.call(values, function (this: unknown, v: number) {
return [v, v * (this as Scale).k];
}, scale).join(","));
const parsed: any = JSON.parse("[1, 2, 3]");
const sum = { total: 0 };
parsed.forEach(function (this: { total: number }, v: number) {
this.total += v;
}, sum);
console.log(sum.total, parsed.map(function (this: Scale, v: number) { return v * this.k; }, scale).join(","));
class Counter {
total = 0;
addAll(items: number[]): number {
Array.prototype.forEach.call(items, (v: number) => {
this.total += v;
});
return this.total;
}
}
console.log(new Counter().addAll(values));