使用Babel和Webpack时IE11报“Object doesn't support property or method 'find'”错误
从你描述的情况来看,这个问题确实有点特殊:Array.prototype.find明明存在,原生数组调用find正常,但你的columns数组(Array.isArray返回true)调用find却报错,而且只在发布后出现。结合这些信息,我整理了几个核心排查和解决方向:
1. 先确认columns是否是真正的原生数组
IE11中,Array.isArray是通过判断对象的内部[[Class]]属性返回true的,但如果数组的原型链被修改(比如__proto__被设为null,或是被第三方库包装过),即使Array.isArray返回true,它也可能没继承Array.prototype上的find方法。
你可以在IE控制台执行这两个命令验证:
// 检查原型是否正常指向Array.prototype console.log(columns.__proto__ === Array.prototype); // 检查是否是Array实例 console.log(columns instanceof Array);
如果第一个命令返回false,说明这个数组的原型有问题。解决方法是在调用find前,把它转换成原生数组:
const getColumnByName = (columns, columnName) => { // 转换成原生数组,确保原型链正常 const nativeColumns = Array.isArray(columns) ? Array.from(columns) : columns; return nativeColumns.find((col) => col.Name === columnName); }
(如果你的IE11不支持Array.from,可以用[...columns]或者Array.prototype.slice.call(columns)替代)
2. 检查Babel Polyfill的注入是否正确
你已经在entry里添加了babel-polyfill,但发布后可能因为打包配置问题导致polyfill没有被正确注入:
- 确保
babel-polyfill是entry的第一个元素:它需要在所有业务代码之前加载,才能全局注入polyfill。 - 升级到更现代的Babel配置:你当前使用的
es2015、es2017等preset已经过时,建议改用@babel/preset-env,它可以根据目标浏览器按需注入polyfill,避免生产环境被tree-shaking误删。
修改你的babel配置示例:
{ test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel-loader', query: { presets: [ 'react', ['@babel/preset-env', { targets: { ie: 11, browsers: ['last 2 versions', 'ie >= 11'] }, useBuiltIns: 'entry', corejs: 3 // 需要提前安装core-js@3 }], 'stage-2' ], plugins: ['transform-class-properties'] } }
同时把entry里的babel-polyfill替换为@babel/polyfill(如果使用Babel 7+),或者直接使用core-js/stable和regenerator-runtime/runtime:
entry: [ 'core-js/stable', 'regenerator-runtime/runtime', './Scripts/App.js', ],
3. 手动添加Array.find的polyfill作为兜底
如果上面的方法都无效,可以在你的入口文件最顶部手动添加Array.find的polyfill,确保覆盖所有场景:
// 为IE11添加Array.find的polyfill if (!Array.prototype.find) { Array.prototype.find = function(predicate) { if (this == null) { throw new TypeError('Array.prototype.find called on null or undefined'); } if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } const list = Object(this); const length = list.length >>> 0; const thisArg = arguments[1]; let value; for (let i = 0; i < length; i++) { value = list[i]; if (predicate.call(thisArg, value, i, list)) { return value; } } return undefined; }; }
内容的提问来源于stack exchange,提问作者Jeff Hechler

