BabelがwebpackでコンパイルしたES6 WebアプリでObject.assign()
を使用しようとしていますが、エラーが発生しています:
Uncaught TypeError: Object.assign is not a function
私はすでに babel-loader
を使用してES6をES5にトランスパイルしているため、他のすべてのES6コードは機能しています。それでも、Object.assign()
は、コードベースでimport "babel-core/polyfill"
を実行した後にのみ機能します。私もこれを修正できることがわかります babel-runtimeをインポートすることで ですが、理解したいのですがwhyObject.assign()
は、babel-loader
が実行する以上のものを必要とします— babel-loader
はObject.assign()
を含むすべてを前処理するべきではありませんか?
Babelは、babel-loader
を介して、ES6の違いを変換しますsyntax。 Babel自体は、ES6標準ライブラリ機能(Object.assign
など)に追加することはまったくありません。ポリフィルをロードすると、別のポリフィル core-js
がロードされますが、任意のポリフィルをロードできます。
一部の構文は、ライブラリコードに実装されたアルゴリズムと動作に依存するため、特定のポリフィル機能がロードに依存している場合もあります。 http://babeljs.io/docs/learn-es2015/ のES6機能は、各標準ライブラリ機能がロードされていると想定されるものをリストします。
Object.assign()
はES6仕様の一部である新しいAPIであるため、ほとんどのブラウザーにはまだ実装されていません。参照: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
したがって、babel-core/polyfill
をインポートすると、これにポリフィルが追加され、ES6コードがそれらを使用できるように、他の新しいAPIが追加されます。
babel-loader
は、ES6構文をES5互換コードに変換する単なるトランスパイラーです。
互換性を確認すると、IE 11はobject.assignのWebとモバイルの両方でサポートされていません。また、そのためのpollyfillも提供します。
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
if (typeof Object.assign != 'function') {
Object.assign = function(target, varArgs) {
'use strict';
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
};
}
Babelを使用している場合
https://babeljs.io/docs/plugins/transform-object-assign/
NPMを使用している場合
私は同じ問題に直面しました。バベルに裏付けられたES2015 +のすべての機能を使用しても安全だと思いました。しかし、前述したように、babelは関数ではなく構文のみをポリフィルします(Object.assign、Array.includesはほんの数例です)。 Object.assignの場合、ポリフィルは使用せず、スプレッド演算子を使用します。この場合、babelは実際にObject.assignが見つからない場合にポリフィルします。このコードを見てください:
let obj = {a: 1};
let obj2 = {...obj};
let obj3 = Object.assign({}, obj);
バベルによって次のように変換されます。
"use strict";
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var obj = { a: 1 };
var obj2 = _extends({}, obj);
var obj3 = Object.assign({}, obj);
スプレッドオペレーターの場合、babelはネイティブObject.assignメソッドを使用しようとし、ポリフィルが見つからない場合は使用します。ただし、明示的なObject.assignメソッドは変更されません¯\ _(ツ)_ /¯