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版规范中引入的对call
和apply
方法的更改。
这些方法允许您调用将第一个参数作为调用函数的this
值传递的函数。
在ECMAScript 3上,如果此参数undefined
或为null
,则调用函数的this
值将引用全局对象,例如:
function test () { return this; } test.call(null) === window; // true
但是在ES5中发生了变化,现在应该在没有修改的情况下传递该值,并且导致Object.prototype.toString
抛出exception,因为期望对象参数。
该方法的规范已更改,现在如果this
值引用undefined
或null
则返回字符串"[object Undefined]"
或"[object Null]"
,修复问题(我认为不是很好的事情) ,因为两个结果都感觉错了, undefined
和null
不是对象,它们是原语…这让我记住了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 。