JavaScript中判断原生方法的几种实现方案

作者:闭包旅人时间:2026-10-27 17:09:03浏览:478

本文探讨了JavaScript中检测原生方法(isNative)的多种实现方式。从基础的正则匹配[native code],到处理Safari等浏览器的特殊表现,再到通过字符串替换规避山寨方法的更严谨方案,详细分析了各版本的优缺点及兼容性细节,帮助开发者在库开发中做出合适的选择。

原生方法检测的必要性

现代浏览器不断引入新的全局对象(如Worker),并为现有对象添加新方法。实现兼容性的首要步骤是检测这些特性是否存在,若不存在则提供兼容实现。然而,简单的类型检查如 typeof Array.prototype.map === "function" 往往不足以准确判断,因为第三方库可能已实现该方法,但其实现未必符合标准。因此,需要更精确的 isNative 方法来判断一个函数是否为浏览器原生提供。

基础正则匹配方案

以下是我长期使用的自定义实现版本:

代码如下:

var isNative = function(method){//判定是否为原生方法
return !! method && (/\{\s*\[native code\]\s*\}/.test(method+"") ||
/\{\s*\/\* source code not available \*\/\s*\}/.test(method+""));//这里是为了兼容opera9.x的
  }

针对Safari的改进方案

然而,不同浏览器对原生方法的 toString 输出存在差异。例如 Diego Perini 指出的版本考虑了 Safari 浏览器中原生方法 toString 返回值的特殊性:


代码如下:

var isNative = function(object, method) {
return object && method in object &&
typeof object[method] != 'string' &&
// IE & W3C browser return "[native code]"
// Safari < = 2.0.4 will return "[function]"
/\{\s*\[native code\]\s*\}|^\[function\]$/).test(object[method]);
  }

第二个版本比第一个多接收一个参数,允许指定具体的原生对象及其方法。尽管参数数量不同,但两者的核心逻辑相似,且都未能覆盖所有情况。即使将这两个函数的结果取并集,仍可能无法覆盖所有正确的原生方法判定场景。

伪造方法与检测局限

问题的核心不在于正则表达式是否匹配 [native code]、source code not available 或 [function],因为在 JavaScript 中,很容易通过重写 toString 方法来伪造这些返回值,从而欺骗上述检测逻辑。例如,以下代码可以成功绕过检测:

代码如下:

window.test = {
toString: function() {
return '[function]';
  }
};
isNative(window, 'test'); // true

基于字符串替换的严谨方案

最后,我从 nwmathers 处找到了一个更严谨的实现:


代码如下:

var isNative = (function() {
var s = (window.open + '').replace(/open/g, '');
return function(object, method) {
var m = object ? object[method] : false, r = new RegExp(method, 'g');
return !!(m && typeof m != 'string' && s === (m + '').replace(r, ''));
   };
 })();
作者最新文章