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 相关文章推荐
firefox浏览器下javascript 拖动层效果与原理分析代码
Dec 04 Javascript
Javascript事件热键兼容ie|firefox
Dec 30 Javascript
javascript 事件绑定问题
Jan 01 Javascript
克隆javascript对象的三个方法小结
Jan 12 Javascript
node.js中的http.response.end方法使用说明
Dec 14 Javascript
jquery通过closest选择器修改上级元素的方法
Mar 17 Javascript
jQuery的Cookie封装,与PHP交互的简单实现
Oct 05 Javascript
最常见的左侧分类菜单栏jQuery实现代码
Nov 28 Javascript
JQuery通过后台获取数据遍历到前台的方法
Aug 13 jQuery
Vue v-for循环之@click点击事件获取元素示例
Nov 09 Javascript
jQuery实现简单日历效果
Jul 05 jQuery
三种取消选中单选框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.MVC的模板标签系统(二)
2006/09/05 PHP
PHP读取数据库并按照中文名称进行排序实现代码
2013/01/29 PHP
浅谈PHP中单引号和双引号到底有啥区别呢?
2015/03/04 PHP
php中使用base HTTP验证的方法
2015/04/20 PHP
PHP那些琐碎的知识点(整理)
2017/05/20 PHP
php curl获取https页面内容,不直接输出返回结果的设置方法
2019/01/15 PHP
Yii2.0框架behaviors方法使用实例分析
2019/09/30 PHP
JQuery扩展插件Validate 5添加自定义验证方法
2011/09/05 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
2014/05/29 Javascript
JavaScript中获取高度和宽度函数总结
2014/10/08 Javascript
使用百度地图api实现根据地址查询经纬度
2014/12/11 Javascript
JS实现在页面随时自定义背景颜色的方法
2015/02/27 Javascript
javascript表单控件实例讲解
2016/09/13 Javascript
动态JavaScript所造成一些你不知道的危害
2016/09/25 Javascript
JS 调用微信扫一扫功能
2016/12/22 Javascript
JSON 数据详解及实例代码分析
2017/01/20 Javascript
深入理解vue.js中$watch的oldvalue与newValue
2017/08/07 Javascript
vue cli 3.0 搭建项目的图文教程
2019/05/17 Javascript
js get和post请求实现代码解析
2020/02/06 Javascript
微信小程序pinker组件使用实现自动相减日期
2020/05/07 Javascript
[00:53]2015国际邀请赛 中国区预选赛一触即发
2015/05/14 DOTA
使用tensorflow实现线性回归
2018/09/08 Python
浅谈Python反射 & 单例模式
2019/03/21 Python
Python传递参数的多种方式(小结)
2019/09/18 Python
用python的turtle模块实现给女票画个小心心
2019/11/23 Python
基于python实现操作redis及消息队列
2020/08/27 Python
Html5监听手机摇一摇事件的实现
2019/11/07 HTML / CSS
上班睡觉检讨书
2014/01/09 职场文书
教师考核评语
2014/04/28 职场文书
2014最新实习证明模板
2014/10/02 职场文书
群众路线个人剖析材料及整改措施
2014/11/04 职场文书
幼儿园中秋节活动总结
2015/03/23 职场文书
2015年维修电工工作总结
2015/04/25 职场文书
2016年教师师德师风心得体会
2016/01/12 职场文书
用Python制作灯光秀短视频的思路详解
2021/04/13 Python
使用scrapy实现增量式爬取方式
2022/06/21 Python