babel polyfill已经被包含,但是在IE11上NodeLists中的forEach仍然无法工作。

13
我已经使用Webpack和Babel,并包含了@babel/polyfill,但在IE11上,当尝试对NodeList使用.forEach时,仍然会出现SCRIPT438错误。
这是我的package.json。
{
  ...
  "scripts": {
    "build:js": "webpack --config ./_build/webpack.config.js"
  },
  ...
  "browserslist": [
    "IE 11",
    "last 3 versions",
    "not IE < 11"
  ],
  "babel": {
    "presets": [
      [
        "@babel/preset-env",
        {
          "useBuiltIns": "usage"
        }
      ]
    ]
  },
  "devDependencies": {
    "@babel/core": "^7.1.6",
    "@babel/preset-env": "^7.1.6",
    "babel-loader": "^8.0.4",
    "webpack": "^4.25.1",
    "webpack-cli": "^3.1.2"
  },
  "dependencies": {
    "@babel/polyfill": "^7.0.0"
  }
}

我的webpack.config.js文件:

const path = require('path');
const webpack = require('webpack');

module.exports = (env, argv) => {

  const javascript = {
    test: /\.js$/,
    use: {
      loader: 'babel-loader'
    }
  };

  // config object
  const config = {
    entry: {
      main: './_src/js/main.js',
    },
    devtool: 'source-map',
    output: {
      path: path.resolve(__dirname, '../js'),
      filename: '[name].js',
    },
    module: {
      rules: [javascript]
    }
  }

  return config;
}

最后,我通过webpack和babel运行/_src/main.js

const testList = document.querySelectorAll('.test-list li');

testList.forEach(item => {
  console.log(item.innerHTML);
})
https://babeljs.io/docs/en/babel-polyfill 的文档说,使用 useBuiltIns: "usage" 在 Webpack 中加载它时不需要 importrequire polyfill。但即使我删除该选项并在 main.js 的顶部手动导入整个 polyfill(使我的包变得巨大),它仍会在 IE11 中出错。
那么......我做错了什么?

Babel 不会为此提供 polyfill。 - connexo
1个回答

38

更新:自Babel 7.4.0起,Babel已直接使用core-js而不是将其与@babel/polyfill一起包装。 core-js已经在NodeList上对forEach进行了填充,因此不再需要额外的polyfill了。


babel-polyfill无法填充缺失的Web API/原型方法,如NodeList.prototype.forEach

请注意,您的问题标题有误导性,因为NodeList.prototype.forEach不是ES6功能。迭代集合上的forEach当前仅是候选建议(截至2018年8月)。

只需在JavaScript的顶层包含自己的polyfill:

if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
}

这可能会在 core-js 3 稳定后发生变化:https://github.com/zloirock/core-js/issues/329 如果您开始采用 ES6 中常用的模式,也可以不使用任何 polyfill。
const testList = [...document.querySelectorAll('.test-list li')];

或者
const testList = Array.from(document.querySelectorAll('.test-list li'));

另一个选择是使用 for...of 代替:

const lis = document.querySelectorAll('.test-list li');
for (const li of lis) {
  // li.addEventListener(...) or whatever
}

最后,您也可以采用常见的ES5模式:

var testList = document.querySelectorAll('.test-list li');
Array.prototype.forEach.call(testList, function(li) { /*whatever*/ });

1
Array.from() 在 IE11 上无法使用,因为它不受支持。 - Ramy Rais
@RamyRais 这就是为什么我也加入了ES5的方式。IE 11不支持除constlet关键字之外的任何ES6功能。 - connexo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接