原文标题:Pretty-Printing Variables, Objects, and Functions in JavaScriptCore
原文链接:https://christiantietze.de/posts/2024/07/pretty-printing-javascriptcore/
原文作者:Christian
本文译者:liuzhen932,首发于 liuzhen932 的小窝
默认情况下,JavaScriptCore 中JSValue
的字符串输出(例如,通过我的 console.log
)只会生成一个简单的[object Object]
,这并不太有用。
通过 JSON,可以很容易地对对象进行格式化打印(如果它们只是数据容器):
const obj = { a: 123, b: 456 };
JSON.stringify(obj, null, 4 /* 缩进级别 */);
// =>
// {
// a: 123,
// b: 456
// }
然而,这种方法无法打印函数。
在 JavaScript 中,任何函数都可以转换为字符串并直接打印,因此可以轻松实现这一点:
function addTwo(x) {
return x + 2;
}
addTwo; // => 不调用,仅引用函数
// => function addTwo(x) {
// return x + 2;
// }
在我的研究中,我发现了一个 2005 年的旧 JavaScript dump
函数,它可以手动遍历对象并打印键值对。借助更现代的 ECMAScript 6 功能,可以使用以下代码打印类似 JSON 的对象,同时包含函数:
function dump(obj, level = 0) {
if (typeof obj === "object" && obj !== null) {
const indent = " ".repeat(level + 1);
const entries = Object.entries(obj).map(([key, value]) => {
let entry = `${indent}"${key}": `;
if (typeof value === "object" && value !== null) {
entry += dump(value, level + 1).trim();
} else if (typeof value === "string") {
entry += `"${value}"`;
} else {
entry += `${value}`;
}
return entry;
});
const joinedEntries = entries.join(",\n");
const levelPadding = " ".repeat(level);
return `{ \n${joinedEntries}\n${levelPadding}}`;
} else {
return `${obj} (${typeof obj})`;
}
}
用法:
const obj = {
f: (x) => x + 4,
a: 123,
b: { ba: 555, bb: "hello" },
};
dump(obj);
// =>
// {
// 'f': (x) => x + 4,
// 'a': 123,
// 'b': {
// 'ba': 555,
// 'bb': "hello"
// }
// }
这会生成一个字符串表示形式,该表示本身在执行时是有效的 JavaScript:
eval(`(${dump(obj)})`).f(1); // => 5
可能已经有一个 Node 包能实现这一点并做得更多,但对我来说,这足以通过我的应用程序中的 REPL 从 JavaScriptCore 内部检查对象。