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 相关文章推荐
javascript 动态参数判空操作
Dec 22 Javascript
jQuery随便控制任意div隐藏的方法
Jun 28 Javascript
面向对象继承实例(a如何继承b问题)(自写)
Jul 01 Javascript
javascript与cookie 的问题详解
Nov 11 Javascript
jquery UI Datepicker时间控件的使用方法(基础版)
Nov 07 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
Jul 15 Javascript
js实现四舍五入完全保留两位小数的方法
Aug 02 Javascript
js判断checkbox是否选中个数的方法(超简单)
Aug 19 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
Dec 14 Javascript
jQuery EasyUI之验证框validatebox实例详解
Apr 10 jQuery
LayerClose弹窗关闭刷新方法
Aug 17 Javascript
JS继承实现方法及优缺点详解
Sep 02 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与XML的PDF文档生成技术
2006/10/09 PHP
社区(php&&mysql)一
2006/10/09 PHP
php 带逗号千位符数字的处理方法
2012/01/10 PHP
php找出指定范围内回文数且平方根也是回文数的方法
2015/03/23 PHP
PHP开发的微信现金红包功能示例
2017/06/29 PHP
解决laravel(5.5)访问public报错的问题
2019/10/12 PHP
ASP.NET jQuery 实例2 (表单中使用回车在TextBox之间向下移动)
2012/01/13 Javascript
js history对象简单实现返回和前进
2013/10/30 Javascript
jquery单选框radio绑定click事件实现方法
2015/01/14 Javascript
javascript日期操作详解(脚本之家整理)
2015/09/05 Javascript
js实现跨域访问的三种方法
2015/12/09 Javascript
jQuery 利用$.ajax 时获取原生XMLHttpRequest 对象的方法
2016/08/25 Javascript
javascript动画之磁性吸附效果篇
2016/12/09 Javascript
Bootstrap如何激活导航状态
2017/03/22 Javascript
js学习总结_选项卡封装(实例讲解)
2017/07/13 Javascript
jquery实现企业定位式导航效果
2018/01/01 jQuery
Vue2.0实现组件数据的双向绑定问题
2018/03/06 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
2018/12/05 jQuery
Vue使用localStorage存储数据的方法
2019/05/27 Javascript
vue input标签通用指令校验的实现
2019/11/05 Javascript
Vue.extend 编程式插入组件的实现
2019/11/18 Javascript
微信小程序开发中var that =this的用法详解
2020/01/18 Javascript
Python开发编码规范
2006/09/08 Python
pandas 选择某几列的方法
2018/07/03 Python
对Keras中predict()方法和predict_classes()方法的区别说明
2020/06/09 Python
python实现马丁策略的实例详解
2021/01/15 Python
CSS3实现伪类hover离开时平滑过渡效果示例
2017/08/10 HTML / CSS
TCP/IP的分层模型
2013/10/27 面试题
质检的岗位职责
2013/11/17 职场文书
2014年导购员工作总结
2014/11/18 职场文书
市场营销计划书范文
2015/01/16 职场文书
我们的节日元宵节活动总结
2015/02/06 职场文书
小学六一主持词开场白
2015/05/28 职场文书
投诉信回复范文
2015/07/03 职场文书
SQL实现LeetCode(180.连续的数字)
2021/08/04 MySQL
Python集合的基础操作
2021/11/01 Python