JavaScript中判断原生函数检查function是否是原生代码


Posted in Javascript onSeptember 09, 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 相关文章推荐
JS中setInterval、setTimeout不能传递带参数的函数的解决方案
Apr 28 Javascript
jquery对象和DOM对象的区别介绍
Aug 09 Javascript
js 三级关联菜单效果实例
Aug 13 Javascript
js左右弹性滚动对联广告代码分享
Feb 19 Javascript
JavaScript中的无阻塞加载性能优化方案
Oct 10 Javascript
jQuery仿gmail实现fixed布局的方法
May 27 Javascript
swiper动态改变滑动内容的实现方法
Jan 17 Javascript
Vue无限滑动周选择日期的组件的示例代码
Jul 18 Javascript
js实现ATM机存取款功能
Oct 27 Javascript
JavaScript如何把两个数组对象合并过程解析
Oct 10 Javascript
Vue 样式切换及三元判断样式关联操作
Aug 09 Javascript
让JavaScript代码更加精简的方法技巧
Jun 01 Javascript
三种取消选中单选框radio的方法
Sep 09 #Javascript
使用JQuery库提供的扩展功能实现自定义方法
Sep 09 #Javascript
JQuery 给元素绑定click事件多次执行的解决方法
Sep 09 #Javascript
一个实用的图片切换支持点击切换和自动轮播
Sep 09 #Javascript
用JavaScript实现用一个DIV来包装文本元素节点
Sep 09 #Javascript
点击button获取text内容并改变样式的js实现
Sep 09 #Javascript
js 数组去重的四种实用方法
Sep 09 #Javascript
You might like
php获取bing每日壁纸示例分享
2014/02/25 PHP
PHP利用func_get_args和func_num_args函数实现函数重载实例
2014/11/12 PHP
WordPress中转义HTML与过滤链接的相关PHP函数使用解析
2015/12/22 PHP
php判断是否为ajax请求的方法
2016/11/29 PHP
FireFox JavaScript全局Event对象
2009/06/14 Javascript
获取客户端网卡MAC地址和IP地址实现JS代码
2013/03/17 Javascript
js随机颜色代码的多种实现方式
2013/04/23 Javascript
JS操作Cookie写入和读取实例代码
2013/10/20 Javascript
JQuery实现倒计时按钮具体方法
2013/11/14 Javascript
JavaScript判断图片是否已经加载完毕的方法汇总
2016/02/05 Javascript
最全面的JS倒计时代码
2016/09/17 Javascript
jQuery的extend方法【三种】
2016/12/14 Javascript
浅谈React和Redux的连接react-redux
2017/12/04 Javascript
jQuery图片查看插件Magnify开发详解
2017/12/25 jQuery
详解vue项目打包步骤
2019/03/29 Javascript
如何在微信小程序中实现Mixins方案
2019/06/20 Javascript
vue实现页面滚动到底部刷新
2019/08/16 Javascript
vue实现两个区域滚动条同步滚动
2020/12/13 Vue.js
python算法学习之计数排序实例
2013/12/18 Python
在python plt图表中文字大小调节的方法
2019/07/08 Python
python中调试或排错的五种方法示例
2019/09/12 Python
如何在Django中使用聚合的实现示例
2020/03/23 Python
Python命名空间namespace及作用域原理解析
2020/06/05 Python
python tqdm库的使用
2020/11/30 Python
详解html5页面 rem 布局适配方法
2018/01/12 HTML / CSS
新西兰最大的连锁超市:Countdown
2020/06/04 全球购物
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
大学生职业生涯规划范文
2013/12/31 职场文书
授权委托书
2014/09/17 职场文书
2014领导干部学习焦裕禄同志先进事迹思想汇报
2014/09/19 职场文书
运动会加油稿100字
2014/09/19 职场文书
卫生主题班会
2015/08/14 职场文书
大学生就业指导课心得体会
2016/01/15 职场文书
Python中的xlrd模块使用整理
2021/06/15 Python
python turtle绘制多边形和跳跃和改变速度特效
2022/03/16 Python
MySQL多表查询机制
2022/03/17 MySQL