¿Por qué babel reescribe la llamada de función importada en (0, fn) (…)?


100

Dado un archivo de entrada como

import { a } from 'b';

function x () {
  a()
}

babel lo compilará para

'use strict';

var _b = require('b');

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

pero cuando se compila en modo suelto, la llamada a la función se emite como _b.a();

He investigado un poco dónde se agrega el operador de coma con la esperanza de que haya un comentario que lo explique. El código responsable de agregarlo está aquí .


4
Deberían haberlo hecho _b.a.call()para dejar clara la intención.
Bergi

@Bergi Estoy seguro de que la razón por la que usan (0,) es para ahorrar espacio en el código transpilado.
Andy


Respuestas:


138

(0, _b.a)()asegura que la función _b.ase llame con thisel objeto global establecido (o si el modo estricto está habilitado, en undefined). Si tuviera que llamar _b.a()directamente, entonces _b.ase llama con thisconfigurado en _b.

(0, _b.a)(); es equivalente a

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

( ,es el operador de coma, consulte https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator ).


3
Gracias por el enlace. pasó por alto esto tantas veces y finalmente decidió averiguar qué estaba pasando.
theflowersoftime

@RobW Creo que agregar var _a = (0, _b.a)en la parte superior del archivo y luego llamar _aahorraría más espacio en muchos casos, ¿alguna idea de que no hicieron eso?
Andy

1
@Andy Tu sugerencia puede tener efectos secundarios, por ejemplo, cuándo _b.aes un captador (dinámico).
Rob W

@RobW Ya veo, entonces estás diciendo que la idea es evitar posibles efectos secundarios hasta que sea necesario llamar a la función.
Andy

Tenga en cuenta que los módulos siempre son código estricto, por lo que siempre lo es this === undefinedy ni siquiera necesita mencionar el objeto global
Bergi

22

El operador de coma evalúa cada uno de sus operandos (de izquierda a derecha) y devuelve el valor del último operando.

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

Entonces, veamos un ejemplo:

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

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

Ahora, en foométodo, thises igual a a(porque foose adjunta a a). Entonces, si llama a.foo() directamente, iniciará sesión falseen la consola.

Pero, si te llamaras (0, a.foo)(). La expresión (0, a.foo)evaluará cada uno de sus operandos (de izquierda a derecha) y devolverá el valor del último operando. En otras palabras, (0, a.foo)es equivalente a

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

Dado que esta función ya no está asociada a nada, thises el objeto global window. Es por eso que inicia sesión trueen la consola cuando llama (0, a.foo)().


la ejecución console.log(this === window);en la consola de desarrollo ya no registra la impresión.
kushdilip

2
Esto me estaba volviendo loco. La clave aquí es que el operador Comma "devuelve el valor del último operando" - el "valor" aquí es la función en sí misma sin su padre contenedor - por lo que foo ya no vive dentro de a.
martinp999
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.