JavaScript检查某个function是否是原生代码的方法


Posted in Javascript onAugust 20, 2014

我总是经常碰到需要检查某个function是否是原生代码的情况 —— 这是功能测试中一个很重要的内容: 函数是浏览器内置支持的,还是通过第三方类库模拟的。要检测这一点,最简单的办法当然是判断函数的 toString 方法返回的值啦。

JavaScript代码

判断函数是否是原生方法其实相当简单:

// 判断是否原生函数 
function isNative(fn) { 
// 示例: 
// alert.toString() 
// "function alert() { [native code] }" 
// '' + fn 利用了js的隐式类型转换. 
return (/\{\s*\[native code\]\s*\}/).test('' + fn); 
}

将函数转换为字符串表示的形式,并且执行正则匹配,这就是实现的原理。

升级版,Update!

;(function() { 

// 取得Object的toString方法,用于处理传入参数value的内部(internal) `[[Class]]` 
var toString = Object.prototype.toString; 

// 取得原始的Function的toString方法,用于处理functions的反编译代码 
var fnToString = Function.prototype.toString; 

// 用于检测 宿主对象构造器(host constructors), 
// (Safari > 4; 真的输出特定的数组,really typed array specific) 
var reHostCtor = /^\[object .+?Constructor\]$/; 

// 使用RegExp将常用的native方法编译为正则模板. 
// 使用 `Object#toString` 是因为一般他不会被污染 
var reNative = RegExp('^' + 
// 将 `Object#toString` 强转为字符串 
String(toString) 
// 对所有正则表达式相关的特殊字符进行转义 
.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&') 
// 为了保持模板的通用性,将 `toString` 替换为 `.*?` 
// 将`for ...`之类的字符替换,兼容Rhino等环境,因为他们会有额外的信息,如方法的参数数量. 
.replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') 
// 结束符 
+ '$' 
); 

function isNative(value) { 
// 判断 typeof 
var type = typeof value; 
return type == 'function' 
// 使用 `Function#toString`原生方法来调用, 
// 而不是 value 自己的 `toString` 方法, 
// 以免被伪造所欺骗. 
? reNative.test(fnToString.call(value)) 
// 如果type 不是'function', 
// 则需要检查宿主对象(host object)的情形, 
// 因为某些(浏览器)环境会将 typed arrays 之类的东西当作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
Javascript 相关文章推荐
JavaScript利用append添加元素报错的解决方法
Jul 01 Javascript
浅谈Javascript数组索引
Jul 29 Javascript
AngularJS 作用域详解及示例代码
Aug 17 Javascript
BootStrap便签页的简单应用
Jan 06 Javascript
bootstrap 通过加减按钮实现输入框组功能
Nov 15 Javascript
vue中使用cropperjs的方法
Mar 01 Javascript
JavaScript同源策略和跨域访问实例详解
Apr 03 Javascript
node中IO以及定时器优先级详解
May 10 Javascript
javascript sort()对数组中的元素进行排序详解
Oct 13 Javascript
基于vue.js实现购物车
Jan 15 Javascript
vue实现广告栏上下滚动效果
Nov 26 Vue.js
原生JS实现音乐播放器
Jan 26 Javascript
使用时间戳解决ie缓存的问题
Aug 20 #Javascript
js中使用replace方法完成某个字符的转换
Aug 20 #Javascript
js 动态修改css文件用到了cssRule
Aug 20 #Javascript
jquery实现在页面加载的时自动为日期插件添加当前日期
Aug 20 #Javascript
js匿名函数的调用示例(形式多种多样)
Aug 20 #Javascript
javascript对中文按照拼音排序代码
Aug 20 #Javascript
JS辨别访问浏览器判断是android还是ios系统
Aug 19 #Javascript
You might like
兼容性比较好的PHP生成缩略图的代码
2011/01/12 PHP
关于php curl获取301或302转向的网址问题的解决方法
2011/06/02 PHP
PHP表单提交表单名称含有点号(.)则会被转化为下划线(_)
2011/12/14 PHP
php读取der格式证书乱码解决方法
2015/06/22 PHP
Yii2中DropDownList简单用法示例
2016/07/18 PHP
php头像上传预览实例代码
2017/05/02 PHP
关于PHP转换超过2038年日期出错的问题解决
2017/06/28 PHP
php使用json-schema模块实现json校验示例
2019/09/28 PHP
HTTP头隐藏PHP版本号实现过程解析
2020/12/09 PHP
jquery插件制作简单示例说明
2012/02/03 Javascript
Js 冒泡事件阻止实现代码
2013/01/27 Javascript
JS隐藏参数post传值实例
2013/04/18 Javascript
JQuery显示隐藏DIV的方法及代码实例
2015/04/16 Javascript
canvas时钟效果
2017/02/16 Javascript
bootstrap datetimepicker 日期插件在火狐下出现一条报错信息的原因分析及解决办法
2017/03/08 Javascript
JavaScript中的return布尔值的用法和原理解析
2017/08/14 Javascript
vue.js,ajax渲染页面的实例
2018/02/11 Javascript
在vue中使用公共过滤器filter的方法
2018/06/26 Javascript
浅谈Webpack核心模块tapable解析
2018/09/11 Javascript
对vue中v-if的常见使用方法详解
2018/09/28 Javascript
微信小程序自定义底部导航带跳转功能
2018/11/27 Javascript
axios封装与传参示例详解
2020/10/18 Javascript
Python基于pycrypto实现的AES加密和解密算法示例
2018/04/10 Python
Python 3.6 读取并操作文件内容的实例
2018/04/23 Python
使用Python微信库itchat获得好友和群组已撤回的消息
2018/06/24 Python
详解HTML5中CSS外观属性
2020/09/10 HTML / CSS
MYSQL支持事务吗
2013/08/09 面试题
JSF界面控制层技术
2013/06/17 面试题
毕业自我评价范文
2013/11/17 职场文书
《世界多美呀》教学反思
2014/03/02 职场文书
《动手做做看》教学反思
2014/04/09 职场文书
介绍信样本
2015/01/31 职场文书
2016高考感言
2015/08/01 职场文书
使用vue-element-admin框架从后端动态获取菜单功能的实现
2021/04/29 Vue.js
Android开发EditText禁止输入监听及InputFilter字符过滤
2022/06/10 Java/Android
mysql序号rownum行号实现方式
2022/12/24 MySQL