Как не дать Вавилону перенести "это" в "неопределенное"
РЕДАКТИРОВАТЬ: Это не о толстых стрелах. Это также не о передаче этого в IIFE. Это вопрос, связанный с транспортом.
Итак, я создал простой паб-саб для небольшого приложения, над которым я работаю. Я написал это в ES6, чтобы использовать распространение / отдых и сохранить некоторые головные боли. Я настроил это с помощью npm и глотнул, чтобы пропустить это, но это сводит меня с ума.
Я сделал это библиотекой браузера, но понял, что ее можно использовать где угодно, поэтому решил сделать ее совместимой с Commonjs и AMD.
Вот урезанная версия моего кода:
(function(root, factory) {
if(typeof define === 'function' && define.amd) {
define([], function() {
return (root.simplePubSub = factory())
});
} else if(typeof module === 'object' && module.exports) {
module.exports = (root.simplePubSub = factory())
} else {
root.simplePubSub = root.SPS = factory()
}
}(this, function() {
// return SimplePubSub
});
Но независимо от того, что я пытаюсь сделать (например, сделать это переменной и передать ее), она устанавливает ее как неопределенную.
}(undefined, function() {
Возможно, это как-то связано с тем, что Бабель не знает, что это будет, и не переносит это, но есть ли другой способ, которым я могу воспользоваться?
ОБНОВЛЕНИЕ: Проход }((window || module || {}), function() {
вместо этого похоже на работу. Я не уверен, что это лучший подход.
2 ответа
Для Вавилона>= 7.x
Код ES6 имеет два режима обработки:
- "скрипт" - при загрузке файла через
<script>
или любой другой стандартный способ загрузки файла ES5 - "модуль" - когда файл обрабатывается как модуль ES6
В Babel 7.x файлы по умолчанию анализируются как "модуль". Проблема в том, что в модуле ES6 this
является undefined
тогда как в "script"
случай, это варьируется в зависимости от окружающей среды, как window
в скрипте браузера или exports
в коде CommonJS.
В Babel 7 вам нужно будет указать Babel, какой у вас тип файла, если вы хотите избежать такого поведения. Самый простой вариант - использовать "sourceType"
возможность установить sourceType: "unambiguous"
в ваших опциях Babel, которые по сути говорят Babel угадывать тип (scripts vs module), основываясь на наличии import
а также export
заявления. Основным недостатком является то, что технически нормально иметь модуль ES6, который не использует import
или же export
и они будут неправильно рассматриваться как сценарии. С другой стороны, это действительно не так часто.
Кроме того, вы можете использовать Babel 7's "overrides"
возможность установить конкретные файлы в качестве сценариев, например,
overrides: [{
test: "./vendor/something.umd.js",
sourceType: "script",
}],
Любой подход позволяет Babel знать, что некоторые файлы script
типы, и, следовательно, не должны иметь this
конвертировано в undefined
,
Для Вавилона < 7.x
Код ES6 имеет два режима обработки:
- "скрипт" - при загрузке файла через
<script>
или любой другой стандартный способ загрузки файла ES5 - "модуль" - когда файл обрабатывается как модуль ES6
При использовании Babel 6 и babel-preset-es2015
(или Babel 5), Babel по умолчанию предполагает, что файлы, которые он обрабатывает, являются модулями ES6. Проблема в том, что в модуле ES6 this
является undefined
в то время как в случае "сценария", this
варьируется в зависимости от окружающей среды, как window
в скрипте браузера или exports
в коде CommonJS.
Если вы используете Babel, самый простой вариант - написать свой код без оболочки UMD, а затем связать файл, используя что-то вроде Browserify, чтобы автоматически добавить оболочку UMD для вас. Бабель также обеспечивает babel-plugin-transform-es2015-modules-umd
, Оба ориентированы на простоту, поэтому, если вам нужен индивидуальный подход UMD, они могут не подойти вам.
В качестве альтернативы вам нужно было бы явно перечислить все плагины Babel в babel-preset-es2015, убедившись, что исключена обработка модулей babel-plugin-transform-es2015-modules-commonjs
плагин. Обратите внимание, что это также остановит автоматическое добавление use strict
поскольку это тоже является частью спецификации ES6, вы можете добавить обратно babel-plugin-transform-strict-mode
чтобы ваш код был строгим автоматически.
По состоянию на babel-core@6.13
пресеты могут принимать опции, так что вы также можете сделать
{
"presets": [
[ "es2015", { "modules": false } ]
]
}
в вашем конфиге Babel (.babelrc
) использовать babel-preset-es2015
с отключенной обработкой модуля.
Предустановка "es2015" по умолчанию упаковывает вывод Babel в оболочку commonJs. Используйте "babel-preset-es2015-script" (вы должны npm install --save babel-preset-es2015-script
сначала) вывести на "скрипт" (без модулей). Это наносило ущерб другим библиотекам, которые я упаковывал с помощью Babel.
Предустановка: https://www.npmjs.com/package/babel-preset-es2015-script