Comparing version
@@ -8,2 +8,8 @@ # Changelog | ||
## [v0.3.5](https://github.com/ljharb/for-each/compare/v0.3.4...v0.3.5) - 2025-02-10 | ||
### Commits | ||
- [New] add types [`6483c1e`](https://github.com/ljharb/for-each/commit/6483c1e9b6177e5ca9ba506188300c5a25de26c2) | ||
## [v0.3.4](https://github.com/ljharb/for-each/compare/v0.3.3...v0.3.4) - 2025-01-24 | ||
@@ -10,0 +16,0 @@ |
15
index.js
@@ -8,2 +8,3 @@ 'use strict'; | ||
/** @type {<This, A extends readonly unknown[]>(arr: A, iterator: (this: This | void, value: A[number], index: number, arr: A) => void, receiver: This | undefined) => void} */ | ||
var forEachArray = function forEachArray(array, iterator, receiver) { | ||
@@ -21,2 +22,3 @@ for (var i = 0, len = array.length; i < len; i++) { | ||
/** @type {<This, S extends string>(string: S, iterator: (this: This | void, value: S[number], index: number, string: S) => void, receiver: This | undefined) => void} */ | ||
var forEachString = function forEachString(string, iterator, receiver) { | ||
@@ -33,2 +35,3 @@ for (var i = 0, len = string.length; i < len; i++) { | ||
/** @type {<This, O>(obj: O, iterator: (this: This | void, value: O[keyof O], index: keyof O, obj: O) => void, receiver: This | undefined) => void} */ | ||
var forEachObject = function forEachObject(object, iterator, receiver) { | ||
@@ -46,3 +49,9 @@ for (var k in object) { | ||
var forEach = function forEach(list, iterator, thisArg) { | ||
/** @type {(x: unknown) => x is readonly unknown[]} */ | ||
function isArray(x) { | ||
return toStr.call(x) === '[object Array]'; | ||
} | ||
/** @type {import('.')._internal} */ | ||
module.exports = function forEach(list, iterator, thisArg) { | ||
if (!isCallable(iterator)) { | ||
@@ -57,3 +66,3 @@ throw new TypeError('iterator must be a function'); | ||
if (toStr.call(list) === '[object Array]') { | ||
if (isArray(list)) { | ||
forEachArray(list, iterator, receiver); | ||
@@ -66,3 +75,1 @@ } else if (typeof list === 'string') { | ||
}; | ||
module.exports = forEach; |
{ | ||
"name": "for-each", | ||
"version": "0.3.4", | ||
"version": "0.3.5", | ||
"description": "A better forEach", | ||
@@ -37,2 +37,3 @@ "keywords": [], | ||
"lint": "eslint --ext=js,mjs .", | ||
"postlint": "tsc && attw -P", | ||
"version": "auto-changelog && git add CHANGELOG.md", | ||
@@ -45,3 +46,7 @@ "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" | ||
"devDependencies": { | ||
"@arethetypeswrong/cli": "^0.17.3", | ||
"@ljharb/eslint-config": "^21.1.1", | ||
"@ljharb/tsconfig": "^0.2.3", | ||
"@types/is-callable": "^1.1.2", | ||
"@types/tape": "^5.8.1", | ||
"auto-changelog": "^2.5.0", | ||
@@ -51,3 +56,4 @@ "eslint": "=8.8.0", | ||
"nyc": "^10.3.2", | ||
"tape": "^5.9.0" | ||
"tape": "^5.9.0", | ||
"typescript": "next" | ||
}, | ||
@@ -54,0 +60,0 @@ "testling": { |
@@ -9,2 +9,3 @@ 'use strict'; | ||
t.plan(4); | ||
forEach({ a: 1, b: 2 }, function (value, key) { | ||
@@ -33,13 +34,26 @@ if (count === 0) { | ||
test('second argument: iterator', function (t) { | ||
/** @type {unknown[]} */ | ||
var arr = []; | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr); }, TypeError, 'undefined is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, null); }, TypeError, 'null is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, ''); }, TypeError, 'string is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, /a/); }, TypeError, 'regex is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, true); }, TypeError, 'true is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, false); }, TypeError, 'false is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, NaN); }, TypeError, 'NaN is not a function'); | ||
// @ts-expect-error | ||
t['throws'](function () { forEach(arr, 42); }, TypeError, '42 is not a function'); | ||
t.doesNotThrow(function () { forEach(arr, function () {}); }, 'function is a function'); | ||
// @ts-expect-error TODO fixme | ||
t.doesNotThrow(function () { forEach(arr, setTimeout); }, 'setTimeout is a function'); | ||
/* eslint-env browser */ | ||
@@ -49,2 +63,3 @@ if (typeof window !== 'undefined') { | ||
} | ||
t.end(); | ||
@@ -54,3 +69,3 @@ }); | ||
test('array', function (t) { | ||
var arr = [1, 2, 3]; | ||
var arr = /** @type {const} */ ([1, 2, 3]); | ||
@@ -67,2 +82,3 @@ t.test('iterates over every item', function (st) { | ||
st.plan(arr.length); | ||
forEach(arr, function (item) { | ||
@@ -72,2 +88,3 @@ st.equal(arr[index], item, 'item ' + index + ' is passed as first argument'); | ||
}); | ||
st.end(); | ||
@@ -79,6 +96,8 @@ }); | ||
st.plan(arr.length); | ||
forEach(arr, function (item, index) { | ||
forEach(arr, function (_item, index) { | ||
st.equal(counter, index, 'index ' + index + ' is passed as second argument'); | ||
counter += 1; | ||
}); | ||
st.end(); | ||
@@ -89,5 +108,7 @@ }); | ||
st.plan(arr.length); | ||
forEach(arr, function (item, index, array) { | ||
forEach(arr, function (_item, _index, array) { | ||
st.deepEqual(arr, array, 'array is passed as third argument'); | ||
}); | ||
st.end(); | ||
@@ -98,5 +119,7 @@ }); | ||
var context = {}; | ||
forEach([], function () { | ||
st.equal(this, context, '"this" is the passed context'); | ||
}, context); | ||
st.end(); | ||
@@ -114,15 +137,19 @@ }); | ||
}; | ||
var keys = ['a', 'b', 'c']; | ||
var keys = /** @type {const} */ (['a', 'b', 'c']); | ||
var F = function F() { | ||
/** @constructor */ | ||
function F() { | ||
this.a = 1; | ||
this.b = 2; | ||
}; | ||
} | ||
F.prototype.c = 3; | ||
var fKeys = ['a', 'b']; | ||
var fKeys = /** @type {const} */ (['a', 'b']); | ||
t.test('iterates over every object literal key', function (st) { | ||
var counter = 0; | ||
forEach(obj, function () { counter += 1; }); | ||
st.equal(counter, keys.length, 'iterated ' + counter + ' times'); | ||
st.end(); | ||
@@ -133,4 +160,7 @@ }); | ||
var counter = 0; | ||
forEach(new F(), function () { counter += 1; }); | ||
st.equal(counter, fKeys.length, 'iterated ' + fKeys.length + ' times'); | ||
st.end(); | ||
@@ -142,2 +172,3 @@ }); | ||
st.plan(keys.length); | ||
forEach(obj, function (item) { | ||
@@ -147,2 +178,3 @@ st.equal(obj[keys[index]], item, 'item at key ' + keys[index] + ' is passed as first argument'); | ||
}); | ||
st.end(); | ||
@@ -154,6 +186,8 @@ }); | ||
st.plan(keys.length); | ||
forEach(obj, function (item, key) { | ||
forEach(obj, function (_item, key) { | ||
st.equal(keys[counter], key, 'key ' + key + ' is passed as second argument'); | ||
counter += 1; | ||
}); | ||
st.end(); | ||
@@ -164,5 +198,7 @@ }); | ||
st.plan(keys.length); | ||
forEach(obj, function (item, key, object) { | ||
forEach(obj, function (_item, _key, object) { | ||
st.deepEqual(obj, object, 'object is passed as third argument'); | ||
}); | ||
st.end(); | ||
@@ -173,5 +209,7 @@ }); | ||
var context = {}; | ||
forEach({}, function () { | ||
st.equal(this, context, '"this" is the passed context'); | ||
}, context); | ||
st.end(); | ||
@@ -184,6 +222,8 @@ }); | ||
test('string', function (t) { | ||
var str = 'str'; | ||
var str = /** @type {const} */ ('str'); | ||
t.test('second iterator argument', function (st) { | ||
var counter = 0; | ||
st.plan((str.length * 2) + 1); | ||
forEach(str, function (item, index) { | ||
@@ -194,6 +234,9 @@ st.equal(counter, index, 'index ' + index + ' is passed as second argument'); | ||
}); | ||
st.equal(counter, str.length, 'iterates ' + str.length + ' times'); | ||
st.end(); | ||
}); | ||
t.end(); | ||
}); |
Sorry, the diff of this file is not supported yet
23915
12.36%13
18.18%266
26.07%11
83.33%