jQuery的isFunction和InternetExplorer

在适应jQuery的isFunction方法时

isFunction: function( obj ) { return toString.call(obj) === "[object Function]"; } 

InternetExlorer 8返回以下错误:“对象不支持此属性或方法”。 深入研究这个函数的好文章不会解决这个问题。 为了检查是否定义了obj ,我在参考MSDN文章时更改了该函数:

 isFunction: function( obj ) { return obj && toString.call(obj) === "[object Function]"; } 

解决方案的任何其他想法?

您需要直接从Object.prototype对象调用toString方法:

 function isFunction (obj) { return Object.prototype.toString.call(obj) === "[object Function]"; } alert(isFunction({})); // false alert(isFunction(function{})); // true 

jQuery有一个名为toString的局部变量,它引用Object.prototype上的方法。

只调用toString.call(obj); 没有声明范围上的toString标识符,适用于Firefox,Chrome等,只是因为Global对象inheritance自Object.prototype ,但规范并不能保证这一点。

 Object.prototype.isPrototypeOf(window); // false on IE 

您链接的文章讨论了ECMAScript第5版规范中引入的对callapply方法的更改。

这些方法允许您调用将第一个参数作为调用函数的this值传递的函数。

在ECMAScript 3上,如果此参数undefined或为null ,则调用函数的this值将引用全局对象,例如:

 function test () { return this; } test.call(null) === window; // true 

但是在ES5中发生了变化,现在应该在没有修改的情况下传递该值,并且导致Object.prototype.toString抛出exception,因为期望对象参数。

该方法的规范已更改,现在如果this值引用undefinednull则返回字符串"[object Undefined]""[object Null]" ,修复问题(我认为不是很好的事情) ,因为两个结果都感觉错了, undefinednull 不是对象,它们是原语…这让我记住了typeof null == 'object' …而且我认为它与[[Class]]的概念混淆了[[Class]]内部财产,无论如何…)

现在您可能想知道为什么jQuery使用此方法来检查函数对象,而不是使用typeof运算符?

实施错误,例如在Chrome / Safari / WebKit中,RegExp对象的typeof返回"function" ,因为RegExp对象可以调用 ,例如:

 typeof /foo/; // "function" in Chrome/Safari/WebKit 

如果对象实现[[Call]]内部属性,则typeof运算符返回"function" ,这使得对象可以调用

这最初是由Mozilla实现引入的,调用RegExp对象相当于调用exec方法。

isFunction函数试图服务的目的是什么? 它是打算处理宿主对象(即浏览器中的DOM节点, window等),还是正则表达式(正如CMS在注释中指出的那样是可调用的,并且在某些浏览器中返回带有typeof “function”)? 如果没有,您只需要

 typeof obj == "function" 

如果它应该处理主机方法,那么它是有缺陷的,因为浏览器没有义务为主机方法返回“[object Function]”。 在IE中有许多可调用的主机属性,它们不会返回“[object Function]”或会抛出错误。 例如:

 alert(Object.prototype.toString.call(document.createElement)); 

…在IE中给出“[object Object]”。

我刚刚在IE 8的控制台中运行它:

 >>$.isFunction(undefined); false 

工作良好。

您引用的博客文章涉及IE 9