IE 11中使用Object.keys出现问题求助
首先,这个报错"Object.keys : l’argument n’est pas un objet Object"在IE11里出现,核心原因是IE11对Object.keys的参数校验比现代浏览器严格得多——尤其是针对宿主对象(比如某些DOM对象、file://环境下的特殊对象),IE11可能不认为它们是标准的Object类型,导致调用时直接抛出错误。结合你需要支持file://内网应用的场景,给你几个可行的解决办法:
1. 封装兼容的键获取函数
直接替换掉原生Object.keys的调用,用一个带兜底逻辑的函数来处理IE11的异常:
function getSafeObjectKeys(obj) { // 先处理null/undefined的边界情况 if (obj == null) { return []; } // 优先尝试原生Object.keys,失败则降级到for-in循环 if (typeof obj === 'object') { try { return Object.keys(obj); } catch (e) { const keys = []; // 遍历对象自身属性,排除原型链上的属性 for (const key in obj) { if (obj.hasOwnProperty(key)) { keys.push(key); } } return keys; } } // 非对象类型直接返回空数组 return []; }
之后把代码里所有Object.keys(xxx)替换成getSafeObjectKeys(xxx)即可,这个函数会在原生方法报错时自动降级,确保IE11不会抛出异常。
2. 针对性处理类数组对象
如果报错是因为传入了类数组对象(比如DOM NodeList、自定义类数组),IE11的Object.keys对这类对象的支持也有缺陷,可以在函数里追加特殊处理:
function getSafeObjectKeys(obj) { if (obj == null) { return []; } // 处理类数组对象(有length属性但不是数组) if (typeof obj === 'object' && 'length' in obj && !Array.isArray(obj)) { const keys = []; // 先收集索引键 for (let i = 0; i < obj.length; i++) { keys.push(String(i)); } // 再追加非索引的自身属性 for (const key in obj) { if (obj.hasOwnProperty(key) && isNaN(Number(key))) { keys.push(key); } } return keys; } // 标准对象的兼容逻辑 if (typeof obj === 'object') { try { return Object.keys(obj); } catch (e) { const keys = []; for (const key in obj) { if (obj.hasOwnProperty(key)) { keys.push(key); } } return keys; } } return []; }
3. file://环境下的对象包装技巧
在file://协议下,IE11的安全策略可能导致某些对象无法被识别为标准Object。可以尝试将这类对象包装成一个新的字面量对象:
// 假设obj是导致报错的目标对象 const wrappedObj = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { wrappedObj[key] = obj[key]; } } // 再调用兼容函数处理包装后的对象 const keys = getSafeObjectKeys(wrappedObj);
如果你的项目已经引入了Object.assign的polyfill(IE11原生不支持),也可以用const wrappedObj = Object.assign({}, obj)快速完成包装。
4. 补充必要的Polyfill
如果代码中用到了其他ES6+ API,建议补充基础的polyfill(比如Object.assign),注意在file://环境下确保polyfill能正常加载,或者直接嵌入代码片段:
if (typeof Object.assign !== 'function') { Object.assign = function(target) { 'use strict'; if (target == null) { throw new TypeError('Cannot convert undefined or null to object'); } target = Object(target); for (var index = 1; index < arguments.length; index++) { var source = arguments[index]; if (source != null) { for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } } return target; }; }
这些方法的核心思路是避免直接依赖IE11对Object.keys的严格校验,通过兜底逻辑和对象包装来适配IE11的特殊行为,应该能解决你遇到的兼容问题。
内容的提问来源于stack exchange,提问作者ygini

