JavaScript检查某个function是否是原生代码的方法
我总是经常碰到需要检查某个function是否是原生代码的情况——这是功能测试中一个很重要的内容:函数是浏览器内置支持的,还是通过第三方类库模拟的。要检测这一点,最简单的办法当然是判断函数的toString方法返回的值啦。
JavaScript代码
判断函数是否是原生方法其实相当简单:
//判断是否原生函数
functionisNative(fn){
//示例:
//alert.toString()
//"functionalert(){[nativecode]}"
//''+fn利用了js的隐式类型转换.
return(/\{\s*\[nativecode\]\s*\}/).test(''+fn);
}
将函数转换为字符串表示的形式,并且执行正则匹配,这就是实现的原理。
升级版,Update!
;(function(){
//取得Object的toString方法,用于处理传入参数value的内部(internal)`[[Class]]`
vartoString=Object.prototype.toString;
//取得原始的Function的toString方法,用于处理functions的反编译代码
varfnToString=Function.prototype.toString;
//用于检测宿主对象构造器(hostconstructors),
//(Safari>4;真的输出特定的数组,reallytypedarrayspecific)
varreHostCtor=/^\[object.+?Constructor\]$/;
//使用RegExp将常用的native方法编译为正则模板.
//使用`Object#toString`是因为一般他不会被污染
varreNative=RegExp('^'+
//将`Object#toString`强转为字符串
String(toString)
//对所有正则表达式相关的特殊字符进行转义
.replace(/[.*+?^${}()|[\]\/\\]/g,'\\$&')
//为了保持模板的通用性,将`toString`替换为`.*?`
//将`for...`之类的字符替换,兼容Rhino等环境,因为他们会有额外的信息,如方法的参数数量.
.replace(/toString|(function).*?(?=\\\()|for.+?(?=\\\])/g,'$1.*?')
//结束符
+'$'
);
functionisNative(value){
//判断typeof
vartype=typeofvalue;
returntype=='function'
//使用`Function#toString`原生方法来调用,
//而不是value自己的`toString`方法,
//以免被伪造所欺骗.
?reNative.test(fnToString.call(value))
//如果type不是'function',
//则需要检查宿主对象(hostobject)的情形,
//因为某些(浏览器)环境会将typedarrays之类的东西当作DOM方法
//此时可能不匹配标准的Native正则模式
:(value&&type=='object'&&reHostCtor.test(toString.call(value)))||false;
};
//可以将isNative赋值给你想要的变量/对象
window.isNative=isNative;
}());
isNative(isNative)//false isNative(alert)//true window.isNative(window.isNative)//false window.isNative(window.alert)//true window.isNative(String.toString)//true