☰
just-entries 源码解析:在 just 零依赖工具库中把对象转换为 [key, value] 对
2026/10/15 2:36:37 网站建设 项目流程
  • 开发工具

【免费下载链接】just

A library of dependency-free JavaScript utilities that do just one thing.

项目地址:https://gitcode.com/gh_mirrors/jus/just
点击查看免费下载

本文以 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-entries
yarn 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; }

从源码结构看,行为可以分成三步:

  1. 参数校验(index.mjs#L17-L19):拒绝所有原始类型(number、string、boolean、undefined)以及null,但显式放行function(typeof obj != 'function'这一条件)。校验失败时抛出带有固定文案的错误:argument to 'entries' must be an object;
  2. 属性枚举(index.mjs#L22-L26):用for...in遍历,再用obj.hasOwnProperty(key)过滤掉原型链上继承来的属性,最终只收集自身的可枚举字符串属性,逐个push([key, obj[key]]);
  3. 返回新数组:不修改传入的对象,纯函数式输出。

整个实现只使用了 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.entriesjust-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.

项目地址:https://gitcode.com/gh_mirrors/jus/just
点击查看免费下载
上一篇:网易云无损音乐解析终极指南:从技术原理到企业级部署
下一篇:fx 终端集成实战:让编码智能体在你的Shell中如鱼得水

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询