尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

es-toolkit/compat isNative 完全指南:识别 JavaScript 引擎原生函数

es-toolkit/compat isNative 完全指南:识别 JavaScript 引擎原生函数 es-toolkit/compat isNative 完全指南识别 JavaScript 引擎原生函数【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkitisNative是 es-toolkit 的es-toolkit/compat模块中用于判断一个值是否为 JavaScript 引擎原生native函数的工具函数。它面向 Lodash 的_.isNative提供 1:1 兼容的调用形式帮助你在浏览器或 Node.js 环境中区分引擎内置函数与用户自定义/第三方库函数例如在 polyfill 策略、运行时环境探测、序列化前安全检查等场景中非常实用。阅读本文后你可以掌握isNative的完整用法、参数与返回值约定并理解其基于Function.prototype.toString与正则匹配的检测原理、core-js 防护机制以及测试用例覆盖的边界情况。功能定位与引入方式isNative属于 es-toolkit 的兼容层。es-toolkit 的 compat 模块介绍英文对应 docs/compat/intro.md说明了该模块的设计目标提供与 Lodash 相同的接口和运行行为让现有 Lodash 代码可以把lodash/lodash-es的导入路径直接替换为es-toolkit/compat调用方代码保持原样。isNative从兼容层统一入口导出对应源码位置为 isNative 实现经由 compat 汇总导出 的export { isNative } from ./predicate/isNative.ts对外提供const result isNative(value);引入方式import { isNative } from es-toolkit/compat;与主模块一致兼容层函数也支持按函数粒度的单独导入对应lodash/merge之类的入口适合 CommonJSrequire()、React Native 等无法树摇的环境例如require(es-toolkit/compat/isNative)。完整用法与示例isNative用于确认给定值是否为 JavaScript 引擎实现的原生函数可以区分浏览器或 Node.js 提供的内建函数。以下示例完整覆盖原生函数、用户自定义函数、库函数、非函数值、绑定函数与对象方法等情况import { isNative } from es-toolkit/compat; // 原生函数 isNative(Array.prototype.push); // true isNative(Object.keys); // true isNative(Math.max); // true isNative(JSON.parse); // true isNative(console.log); // true在浏览器/Node.js 环境中 // 用户自定义函数 isNative(function () {}); // false isNative(() {}); // false isNative(function customFunction() {}); // false // 第三方库函数 isNative(require(lodash).map); // false isNative(require(es-toolkit).chunk); // false // 非函数值 isNative({}); // false isNative([]); // false isNative(function); // false isNative(123); // false isNative(null); // false // 绑定后的函数 const boundFunction Array.prototype.push.bind([]); isNative(boundFunction); // true绑定函数仍是原生实现 // 作为对象方法引用 const obj { method: Array.prototype.push }; isNative(obj.method); // true依然是原生函数几个值得注意的行为要点构造函数也算原生函数。测试用例中Array、Promise、Uint8Array、Object.create、encodeURI等均返回true见 isNative 测试 的第一个用例。bind不改变原生身份。Function.prototype.bind本身是原生实现绑定产物仍由引擎生成因此返回true。通过属性引用原生函数不会去原生化。obj.method只是指向Array.prototype.push的别名判断结果仍为true。非函数值一律返回false包括字符串function、数字、null、对象、数组等不会抛错。参数valueany要检查的值。返回值boolean当值看起来是原生函数时返回true否则返回false。从源码签名看isNative还是一个 TypeScript 类型守卫export function isNative(value: any): value is (...args: any[]) any实现第 32 行这意味着if (isNative(fn))分支内fn会被收窄为可调用函数类型便于在类型层面安全地调用它。源码原理toString 加正则匹配isNative的检测逻辑非常紧凑完整实现见 isNative.ts核心分为三步。第一步函数类型快速短路if (typeof value ! function) { return false; }只有typeof为function的值才进入后续判断这解释了上文非函数值一律false的行为。第二步core-js 防护检查if ((globalThis as any)?.[__core-js_shared__] ! null) { throw new Error(Unsupported core-js use. Try https://npms.io/search?qponyfill.); }实现第 37-39 行__core-js_shared__是 core-js 全局 polyfill 方案的共享标记。core-js 会对原生函数打补丁导致看起来原生的判断不可信因此实现选择直接抛出错误而不是给出可能错误的结果——与其返回不可靠的false不如让调用者显式切换到 ponyfill 方案。测试用例 专门模拟了globalThis.__core-js_shared__ {}的场景并断言isNative会抛错。第三步正则匹配函数源码字符串const functionToString Function.prototype.toString; const REGEXP_SYNTAX_CHARS /[\\^$.*?()[\]{}|]/g; const IS_NATIVE_FUNCTION_REGEXP RegExp( ^${functionToString .call(Object.prototype.hasOwnProperty) .replace(REGEXP_SYNTAX_CHARS, \\$) .replace(/hasOwnProperty|(function).*?(?\\\()| for .?(?\\\])/g, $1.*?)}$ ); return IS_NATIVE_FUNCTION_REGEXP.test(functionToString.call(value));实现第 1-15、41 行构造过程值得逐行拆解先用Function.prototype.toString.call(Object.prototype.hasOwnProperty)拿到引擎对该原生函数的源码字符串。在不同引擎上它形如function hasOwnProperty() { [native code] }或[native code]包裹的具体文本REGEXP_SYNTAX_CHARS把字符串中所有正则元字符\ ^ $ . * ? ( ) [ ] { } |转义保证它可以直接嵌入正则字面量而不被误读第二个replace把函数名和参数列表这两个因引擎而异的部分抹掉用hasOwnProperty|(function).*?(?\\\()| for .?(?\\\])定位统一替换为$1.*?最终得到一个形如^function.*?\(\) { \[native code\] }$的宽容模式——只要函数签名与参数形态一致、主体是[native code]即匹配判断时用functionToString.call(value)取目标函数的源码字符串再测试。注意这里用call而不是value.toString()这一点有实质意义即使攻击者或 bug覆写了目标函数自身的toString属性也拿不到它伪造的字符串因为调用的是从原型链上保存的原始Function.prototype.toString引用。测试用例 验证了这一点给函数定义自定义toString返回function () { [native code] }后isNative仍正确返回false。可以推断这套以真原生函数为模板、抹掉易变部分后生成正则的写法是 Lodash 同款检测策略的忠实移植——不同 JavaScript 引擎对原生函数的toString输出略有差异如是否带函数名、参数列表格式模板化正则避免了逐引擎硬编码。测试用例验证的行为边界isNative.spec.ts 注释中注明了测试对齐自 Lodash 官方测试集lodash/lodash/blob/main/test/isNative.spec.js其覆盖范围比文档示例更广可作为行为契约参考返回true的原生值Array、Object.create、encodeURI、Promise、Array.prototype.slice、Uint8Array、Object.keys、Function.prototype.bind、String.prototype.charAt、Number.prototype.toFixed、Math.max等返回false的非原生值undefined、null、布尔、0/1、字符串、{}、[]、箭头函数、普通函数、new Date()、new Error()、正则、Symbol、Map、Set、WeakMap、WeakSet、ArrayBuffer、DataView等——几乎穷举了所有非函数内置类型core-js 检测抛错注入__core-js_shared__后isNative(noop)抛出异常随后测试在finally中清理全局状态伪造原生函数不被欺骗见上文toString覆写用例。适用场景与注意事项适用环境探测确认某 API 由引擎提供、polyfill/降级决策前的能力检查、对传入回调的来源做安全校验。注意 core-js 限制如果你的项目中以全局方式加载了 core-jspolyfill 模式isNative会直接抛错。此时官方提示是改用 ponyfill 方案测试用例也证明了这是有意设计的行为。注意看起来原生的语义返回值描述为appears to be a native function检测基于toString输出形态。对于极端定制过的运行时如某些 JS 引擎嵌入环境修改了[native code]输出行为可能偏离预期这也是它只存在于 compat 兼容层、面向 Lodash 对齐语义的原因。版本前提以上内容基于当前仓库es-toolkit1.52.0见 package.json中src/compat/predicate/isNative.ts的实现与测试对应 日文兼容文档 及 英文兼容文档 的描述。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表