您现在的位置: 万盛学电脑网 >> 程序编程 >> 脚本专题 >> javascript >> 正文

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

作者:佚名    责任编辑:admin    更新时间:2022-06-22

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

  JavaScript代码

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

  1// 判断是否原生函数

  2function isNative(fn) {

  3// 示例:

  4// alert.toString()

  5// "function alert() { [native code] }"

  6// '' + fn 利用了js的隐式类型转换.

  7return (/{s*[native code]s*}/).test('' + fn);

  8}

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

  升级版,Update!

  01;(function() {

  02

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

  04var toString = Object.prototype.toString;

  05

  06// 取得原始的Function的toString方法,用于处理functions的反编译代码

  07var fnToString = Function.prototype.toString;

  08

  09// 用于检测 宿主对象构造器(host constructors),

  10// (Safari > 4; 真的输出特定的数组,really typed array specific)

  11var reHostCtor = /^[object .+?Constructor]$/;

  12

  13// 使用RegExp将常用的native方法编译为正则模板.

  14// 使用 `Object#toString` 是因为一般他不会被污染

  15var reNative = RegExp('^' +

  16// 将 `Object#toString` 强转为字符串

  17String(toString)

  18// 对所有正则表达式相关的特殊字符进行转义

  19.replace(/[.*+?^${}()|[]/]/g, '$&')

  20// 为了保持模板的通用性,将 `toString` 替换为 `.*?`

  21// 将`for ...`之类的字符替换,兼容Rhino等环境,因为他们会有额外的信息,如方法的参数数量.

  22.replace(/toString|(function).*?(?=()| for .+?(?=])/g, '$1.*?')

  23// 结束符

  24+ '$'

  25);

  26

  27function isNative(value) {

  28// 判断 typeof

  29var type = typeof value;

  30return type == 'function'

  31// 使用 `Function#toString`原生方法来调用,

  32// 而不是 value 自己的 `toString` 方法,

  33// 以免被伪造所欺骗.

  34? reNative.test(fnToString.call(value))

  35// 如果type 不是'function',

  36// 则需要检查宿主对象(host object)的情形,

  37// 因为某些(浏览器)环境会将 typed arrays 之类的东西当作DOM方法

  38// 此时可能不匹配标准的Native正则模式

  39: (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;

  40};

  41

  42// 可以将 isNative 赋值给你想要的变量/对象

  43window.isNative = isNative;

  44}());

  测试代码:

  1isNative(isNative) //false

  2isNative(alert) //true

  3window.isNative(window.isNative) //false

  4window.isNative(window.alert) //true

  5window.isNative(String.toString) //true