Чому Babel перезаписує імпортовану функцію викликає (0, fn) (…)?


100

Дано вхідний файл типу

import { a } from 'b';

function x () {
  a()
}

Вавилон складе його

'use strict';

var _b = require('b');

function x() {
  (0, _b.a)();
}

але при компіляції у вільному режимі виклик функції виводиться як _b.a();

Я провів кілька досліджень того, куди додається оператор коми, сподіваючись, що з’явився коментар, що пояснює це. Код, відповідальний за його додавання, знаходиться тут .


4
Вони повинні були зробити _b.a.call()для того, щоб зрозуміти наміри.
Бергі

@Bergi Я впевнений, що причиною, з якою вони це (0,), є економія місця в перекладеному коді.
Енді


Відповіді:


138

(0, _b.a)()забезпечує _b.aвиклик функції із thisвстановленим на глобальний об'єкт (або якщо суворий режим включений, до undefined). Якщо вам потрібно було дзвонити _b.a()безпосередньо, то _b.aвиклик із thisвстановленим на _b.

(0, _b.a)(); еквівалентно

0; // Ignore result
var tmp = _b.a;
tmp();

( ,це оператор комами, див. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator ).


3
дякую за посилання так багато разів передавав це і нарешті вирішив з’ясувати, що відбувається.
theflowersполовина

@RobW Я б подумав, що додавання var _a = (0, _b.a)у верхній частині файлу, а потім виклик _aзаощадить більше місця у багатьох випадках, будь-яка ідея, що вони цього не робили?
Енді

1
@Andy Ваша пропозиція може мати побічні ефекти, наприклад, коли _b.aце (динамічне) отримання.
Роб Ш

@RobW Я бачу, тому ви говорите ідею - уникати потенційних побічних ефектів, поки функцію не потрібно буде викликати.
Енді

Зауважте, що модулі - це завжди суворий код, тому це завжди, this === undefinedі вам навіть не потрібно згадувати про глобальний об’єкт
Bergi

22

Оператор комами оцінює кожен його операнд (зліва направо) і повертає значення останнього операнда.

console.log((1, 2)); // Returns 2 in console
console.log((a = b = 3, c = 4)); // Returns 4 in console

Отже, давайте подивимось приклад:

var a = {
  foo: function() {
    console.log(this === window);
  }
};

a.foo(); // Returns 'false' in console
(0, a.foo)(); // Returns 'true' in console

Тепер у fooметоді thisдорівнює a(тому що fooдодається a). Тож якщо ви зателефонуєте a.foo() безпосередньо, він увійде falseв консоль.

Але, якби вам дзвонили (0, a.foo)(). Вираз (0, a.foo)оцінить кожен його операнд (зліва направо) і поверне значення останнього операнда. Іншими словами, (0, a.foo)рівнозначно

function() {
  console.log(this === window);
}

Оскільки ця функція більше не прив’язана ні до чого, вона thisє глобальним об’єктом window. Ось чому він входить trueу консоль під час дзвінка (0, a.foo)().


працює console.log(this === window);в консолі розробника, більше не записує друк.
кушдиліп

2
Це дувало моєю думкою. Ключовим тут є те, що оператор Comma "повертає значення останнього операнда" - "значення" тут - сама функція відсутня, що містить її батьківський, тому foo більше не живе всередині a.
martinp999
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.