- 开发工具
【免费下载链接】just
A library of dependency-free JavaScript utilities that do just one thing.
本文以 packages/object-entries/README.md 为核心,完整讲解 just 库中just-entries包的安装方式与全部官方示例,并结合 源码实现、TypeScript 类型定义 与 tape 测试用例,剖析entries()的参数校验逻辑、key/value 枚举规则、异常边界,以及它与原生Object.entries的实际差异,帮助你既能直接使用这个工具,也能理解其底层行为。
just-entries 是什么
just-entries是 just 工具库中的一个独立 npm 包,仓库中的源码位于 packages/object-entries/ 目录。just 的定位是「A library of dependency-free JavaScript utilities that do just one thing」(见根目录 README.md),即每个模块只做一件事且不依赖任何第三方包;just-entries承担的职责非常单一:
Return object entries as an array of [key, value] pairs(把对象的条目返回为
[key, value]对的数组)
从 package.json 可以看到当前版本为2.3.0,description字段与 README 的描述一致,keywords包含object、entries、no-dependencies,许可证为 MIT,且 dependencies 为空——确实零运行时依赖。
安装
README 提供了两种安装方式:
npm install just-entriesyarn add just-entries该包同时提供 ESM 与 CommonJS 两种入口(下文「双格式分发」一节有源码级说明),因此既可以用import entries from 'just-entries'(ESM),也可以用require('just-entries')(CJS),均无需额外转译。
官方使用示例全解
下面是 README 中的完整示例(与 md-variables.json 中just-entries条目的examples数组逐行对应):
import entries from 'just-entries'; // Object: entries({c: 8, a: 4}); // [['c', 8], ['a', 4]] entries({b: {bb: 4}, a: {aa: 2}}); // [['b', {bb: 4}], ['a', {aa: 2}]] entries({}); // [] // Array: entries([{c: 8}, {a: 4}]; // [[0, {c: 8}], [1, {a: 4}]] entries(['À', 'mauvais', 'ouvrier', 'point', 'de', 'bon', 'outil']) // [[0, 'À'], [1, 'mauvais'] ... [6, 'outil']] entries([]); // []逐条拆解这些示例揭示的行为:
- 对象场景:
entries({c: 8, a: 4})返回[['c', 8], ['a', 4]],即按属性插入顺序(c在前、a在后)生成[key, value]对,而不是按 key 字母序排列; - 嵌套值原样保留:
entries({b: {bb: 4}, a: {aa: 2}})中,value 是对象引用,entries不做深拷贝,也不展开嵌套结构,仅把顶层属性拍平成二元组数组; - 空对象:
entries({})返回空数组[],不会抛错; - 数组场景:数组本质是对象,
entries把数字索引(字符串形式)当作 key,元素当作 value。entries([{c: 8}, {a: 4}])得到[[0, {c: 8}], [1, {a: 4}]],第二行的法语谚语字符串数组同理,展开为[[0, 'À'], [1, 'mauvais'], ..., [6, 'outil']]; - 空数组:
entries([])返回[]。
源码实现:参数校验 + for-in 枚举
核心实现在 index.mjs 中,全文不到 15 行:
function entries(obj) { if ((typeof obj != 'object' && typeof obj != 'function') || obj == null) { throw new Error('argument to `entries` must be an object'); } var result = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { result.push([key, obj[key]]); } } return result; }从源码结构看,行为可以分成三步:
- 参数校验(index.mjs#L17-L19):拒绝所有原始类型(
number、string、boolean、undefined)以及null,但显式放行function(typeof obj != 'function'这一条件)。校验失败时抛出带有固定文案的错误:argument to 'entries' must be an object; - 属性枚举(index.mjs#L22-L26):用
for...in遍历,再用obj.hasOwnProperty(key)过滤掉原型链上继承来的属性,最终只收集自身的可枚举字符串属性,逐个push([key, obj[key]]); - 返回新数组:不修改传入的对象,纯函数式输出。
整个实现只使用了 ES5 语法(var、for...in、hasOwnProperty),这也与根 README 中「Most utilities still work with any platform that supports ES5」的平台支持声明相吻合——在Object.entries(ES2017)不可用的旧环境中,just-entries可以当作一个轻量替代。
行为边界:数组、函数与非标准对象
README 示例只覆盖了普通对象和数组,仓库中的 tape 测试文件 补充了更多边界情况,四组测试分别验证:
- regular objects:普通对象返回 property/value 对,包括嵌套对象与空对象;
- arrays:数组返回 index/value 对。注意测试断言写的是
['0', {c: 8}]——数组的 key 是字符串形式的索引,README 中的[0, ...]只是省略引号的简写; - irregular objects(非标准对象):
- 包装对象
new String('hello')返回[['0', 'h'], ['1', 'e'], ['2', 'l'], ['3', 'l'], ['4', 'o']],即按字符索引展开; - 普通函数
entries(function(a, b) {return a + b;})返回[]——函数本身是合法参数,但它没有自身的可枚举属性; - 给函数挂属性
fn.a = 4后,entries(fn)返回[['a', 4]],印证了「放行 function」这一设计;
- 包装对象
- primitives throw:
entries(1)、entries(true)、entries(undefined)、entries(null)四种原始值输入全部抛出Error,与源码校验逻辑一一对应。
TypeScript 类型设计
index.d.ts 用两个重载签名区分「数组输入」与「对象输入」:
export default function entries<T extends any[]>(obj: T): [number, T[number]][]; export default function entries<T extends object>(obj: T): [keyof T, T[keyof T]][];- 传入数组时,key 类型推导为
number,value 类型为数组元素类型T[number]; - 传入对象时,key 类型为
keyof T(具体字面量键的联合),value 类型为对应的属性值类型。
index.tests.ts 是一组「类型即测试」的编译期断言,正例例如:
const test1: ["a" | "b", number][] = entries({ a: 1, b: 2 }); const arrayTest1: [number, number][] = entries([1, 2, 3]); // [[0, 1],[1, 2],[2, 3]] const test3: [never, never][] = entries({});负例则用@ts-expect-error确认以下调用在类型层面被拒绝:entries()、entries(null)、entries(undefined)、entries(1)、entries(true)、entries("a"),以及多传参数的entries([], true)。根目录 tsconfig.json 通过include: ["packages/**/*.tests.ts"]与strict: true收集这些文件,由根 package.json 的test-types脚本(tsc)执行编译期检查。
ES Module 与 CommonJS 双格式分发
package.json 的exports字段声明了三种解析条件:
"exports": { ".": { "types": "./index.d.ts", "require": "./index.cjs", "import": "./index.mjs" }, "./package.json": "./package.json" }即:CJS 环境(require)走 index.cjs,ESM 环境(import)走 index.mjs,TypeScript 类型走 index.d.ts。
从构建配置看,rollup.config.js 只是对仓库公共函数 createRollupConfig 的一次调用,该公共配置的输入是index.cjs、输出是index.mjs(format: 'esm',并挂载@rollup/plugin-commonjs插件)。因此可以推断:CJS 文件是源头,ESM 文件是构建产物,由rollup -c(package.json 的build脚本)生成,二者共享同一段entries函数体,仅导出方式不同(module.exports = entries对export {objectEntries as default})。
CHANGELOG.md 也记录了这一演进过程:2.1.0引入类型定义,2.2.0修正 package.json 的 exports,2.2.1调整导出顺序(default 置后),2.3.0则完成了 node 模块文件.js→.cjs的重命名。
与原生 Object.entries 的差异
just-entries的 API 形态与 ES2017 的Object.entries对齐,但结合源码可以实现上有几处值得注意的不同:
| 对比点 | Object.entries | just-entries |
|---|---|---|
| 输入范围 | 非 null 对象(含函数) | 非原始值、非 null 的对象与函数(校验逻辑) |
| 非法输入错误 | 抛出TypeError | 抛出固定文案的Error:argument to 'entries' must be an object |
| Symbol 键 | 会包含 Symbol 键的属性 | 从源码的for...in枚举方式看,Symbol 键不在遍历范围内,不会被返回 |
| 运行环境要求 | 需要 ES2017 支持 | 纯 ES5 语法,旧环境无需 polyfill |
| 依赖 | 原生 | 零依赖 |
两者在普通对象与数组上的结果一致:都只返回自身可枚举属性,且都遵循相同的键序(字符串键按插入顺序)。
如何运行测试验证
该包的测试不在包目录内,而是集中在根 test/object-entries/index.cjs(包自身的test脚本只是一个占位echo)。在仓库根目录可以这样运行:
# 运行全部单测 + lint + 类型检查 npm test # 只跑 just-entries 的 tape 用例 npx tape ./test/object-entries/index.cjs根 package.json 的test脚本完整流程为:npm run lint && tape ./test/**/index.cjs | tap-spec && npm run test-types,即 ESLint 检查、tape 运行时测试、tsc类型检查三段式。上面「行为边界」一节的所有结论均可以在该测试文件中找到对应断言。
附:README 的自动生成机制
packages/object-entries/README.md 开头的DO NOT EDIT注释说明它并非手写,而是由 scripts/generate-readmes.js 基于 templates/local.template 模板与 md-variables.json 中的变量(packageName、dir、description、examples)渲染生成:模板负责安装命令与代码块的骨架,examples数组提供示例行,description提供功能描述。因此 README 中的示例与md-variables.json保持单一数据源,修改示例只需改 JSON 变量后重新生成。
- 开发工具
【免费下载链接】just
A library of dependency-free JavaScript utilities that do just one thing.
相关推荐
just-index 使用指南:将 JavaScript 数组按指定键快速转为索引对象(零依赖工具 just-index 完整解析)
just index 使用指南:将 JavaScript 数组按指定键快速转为索引对象(零依赖工具 just index 完整解析) just index 是
开发工具RxJS v4 的 Rx.Observable.pairs:把对象优雅地转换为 [key, value] 键值对流
RxJS v4 的 Rx.Observable.pairs:把对象优雅地转换为 key, value 键值对流 Rx.Observable.pairs obj,
后端just-index 4.x 版本演进与源码解析:零依赖把对象数组按字段建成索引
just index 4.x 版本演进与源码解析:零依赖把对象数组按字段建成索引 just index 是 just 库( README.md https://
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考