Javascript 怪异的IE8内部[[class]]属性行为
我最近在IE8上遇到了一些问题(目前我还不知道是9),无法读取和比较一些Javascript 怪异的IE8内部[[class]]属性行为,javascript,dom,browser,internet-explorer-8,local-storage,Javascript,Dom,Browser,Internet Explorer 8,Local Storage,我最近在IE8上遇到了一些问题(目前我还不知道是9),无法读取和比较一些[[Class]]]属性的值。实际上,它只适用于localStorage对象 我用的是这样的方法 var ToStr = Object.prototype.toString; Object.type = function _type( obj ) { var res = ToStr.call( obj ).split( ' ' )[ 1 ].replace( ']', '' ); if( obj === w
[[Class]]]
属性的值。实际上,它只适用于localStorage
对象
我用的是这样的方法
var ToStr = Object.prototype.toString;
Object.type = function _type( obj ) {
var res = ToStr.call( obj ).split( ' ' )[ 1 ].replace( ']', '' );
if( obj === window ) {
res = 'Window';
}
else if( res === 'Window' || res === 'Global' ) {
res = 'Undefined';
}
else if( res.indexOf( 'HTML' ) === 0 ) {
res = 'Node';
}
return ( res );
};
此方法将返回以下值,例如:
var foo = { },
bar = [ ],
num = 52,
win = window;
Object.type( foo ) === 'Object'; // true
Object.type( bar ) === 'Array'; // true
Object.type( num ) === 'Number'; // true
Object.type( win ) === 'Window'; // true
当然,在我所知道的所有浏览器中,只要从对象本身检查[[Class]]]
属性就可以了。现在,我在localStorage
对象上调用这个方法
Object.type( win.localStorage ) === 'Storage' // true (not in IE8)
if( obj === window ) { }
IE8只在这里返回对象
。但是,这并不是真正的问题,当您尝试将localStorage
对象与窗口
对象进行比较时,就会出现问题。如您所见,我正在检查传入的参数是否是当前的窗口
对象
Object.type( win.localStorage ) === 'Storage' // true (not in IE8)
if( obj === window ) { }
如果obj
now是window.localStorage
对象,那么这将导致错误
"Class does not support automation"
只有当您尝试将localStorage
与window
进行比较时,才会发生这种情况,您可以将其与任何其他内容进行比较,而不会遇到任何问题。这只是另一个bug还是我可以解决这个问题
我想基本上我的问题是:
在IE8(也可能是IE9)中,您如何知道您正在处理localStorage
对象?
我最不想做的事情是使用try-catch
对整个方法进行内部包装,因为它经常被调用
让我完全困惑的是:当你在IE8的控制台中执行console.log(obj)
时,它会返回你[object Storage]
(很好!),但是如果你调用object.prototype.toString.call(obj)
,它会返回[object object]
。obj的类型
也是如此,将返回对象
第二个问题:
IE8
控制台如何打印出正确的[[Class]]
?
这一点都不漂亮。获取字符串“[对象存储]”
的唯一方法是使用以下代码:
obj.constructor.toString();
对于任何本机构造函数,输出和其他浏览器中的预期输出都是本机函数的字符串表示形式。然而,我们在这里讨论的是宿主对象,其中完全应用了不同的规则。有趣的是,尽管IE 9对DOM进行了所有改进,但它给出了相同的结果
这不是一个完全有弹性的解决方案,但这是我能在很短的时间内找到的唯一解决方案,我必须看看这个问题
IE8和IE9的IE8文档模式之间似乎存在差异,
localStorage.constructor
在前者中实际上并不存在。在这种情况下,我认为没有其他可行的解决方案。Duck类型似乎并不有效,因为所有localStorage
对象的属性名都有点通用。你可以用
window.localStorage === obj
但我不确定IE8在试图覆盖窗口对象的本机属性时的行为(如果它不允许,那么您可能会没事)。这确实是一个非常奇怪的
IE8
错误!(哦,我爱什么呢
正如IE8
浏览器评论中所述,我认为只有一种解决方案:
typeof obj === "object" && obj.constructor.toString() === "[object Storage]"
在检查之前,请确保当前浏览器是IE8,否则无法工作,即使在其他版本的IE中也无法工作
顺便说一句,IE与“兄弟姐妹”的兼容性是一个很好的例子 你写道:
只有当您尝试将localStorage
与window
进行比较时,才会发生这种情况,您可以将其与任何其他内容进行比较,而不会遇到任何问题
那你为什么不这样做呢
var ToStr = Object.prototype.toString;
Object.type = function _type( obj ) {
if ( window.localStorage && obj === window.localStorage )
return 'Storage';
if ( obj === window )
return 'Window';
var res = ToStr.call( obj ).split( ' ' )[ 1 ].replace( ']', '' );
if ( res === 'Window' || res === 'Global' ) {
return 'Undefined';
if ( res.indexOf( 'HTML' ) === 0 ) {
return 'Node';
return res;
};
直接回答问题的补充:
obj===window.localStorage
即可检查您是否正在处理它。再简单不过了,不是吗应使用Steffen功能检测(见下文),以避免访问
本地存储失败
关于IE8的具体问题,您能否确认该页面正在提供服务,而不是在本地打开?i、 e.URL是http://localhost/hello.html
而不是file:///C:/somefolder/hello.html
IE8不允许对本地打开的文件进行localStorage
,尽管找不到支持这一点的官方文档(但还有和:),可能值得检查一下,您没有在IE7模式下运行浏览器
如果您上面的代码应该检测功能可用性,而不是完全检测其他功能,则可以选择使用以下内容:
我已经找到了一种使用隐式toString()
操作解决IE8行为的方法,ECMAScript规范解释了这种解决方法的意义。隐式的toString()
是:
"" + window.localStorage
这会隐式地强制调用对象的内部toString()
方法,在IE中,这将返回所需的形式[object Storage]
,并且您可以让代码在不使用特殊大小写的情况下工作window.localStorage
所以,我一直在寻找一种风险最小的方法来将其合并到您现有的代码中。选择的方法是以与获取类型相同的方式获取类型,并且当且仅当它返回泛型“对象”类型时,然后查看新方法是否有更好的名称可用。所以,过去一切正常的东西都将继续在wa中发挥作用