Mengapa babel menulis ulang pemanggilan fungsi yang diimpor ke (0, fn) (…)?

100

Diberikan file input seperti

import { a } from 'b';

function x () {
  a()
}

babel akan mengkompilasinya menjadi

'use strict';

var _b = require('b');

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

tetapi ketika dikompilasi dalam mode longgar panggilan fungsi adalah keluaran sebagai _b.a();

Saya telah melakukan beberapa penelitian di mana operator koma ditambahkan dengan harapan ada komentar yang menjelaskannya. Kode yang bertanggung jawab untuk menambahkannya ada di sini .

Will Smith
sumber
4
Mereka seharusnya melakukannya _b.a.call()agar niatnya jelas.
Bergi
@Bergi Saya yakin alasan mereka melakukannya (0,) adalah untuk menghemat ruang dalam kode transparan.
Andy

Jawaban:

138

(0, _b.a)()memastikan bahwa fungsi _b.adipanggil dengan thisset ke objek global (atau jika mode ketat diaktifkan, ke undefined). Jika Anda menelepon _b.a()secara langsung, maka _b.adipanggil dengan thisset ke _b.

(0, _b.a)(); setara dengan

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

( ,adalah operator koma, lihat https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator ).

Rob W.
sumber
3
terima kasih untuk tautannya. melewati ini berkali-kali dan akhirnya memutuskan untuk mencari tahu apa yang terjadi.
theflowersoftime
@RobW Saya akan berpikir menambahkan var _a = (0, _b.a)di bagian atas file dan kemudian menelepon _aakan menghemat lebih banyak ruang dalam banyak kasus, ada ide mereka tidak melakukan itu?
Andy
1
@Andy Saran Anda mungkin memiliki efek samping, misalnya kapan _b.apengambil (dinamis).
Rob W
@RobW Aku mengerti, jadi maksudmu ide adalah untuk menghindari potensi efek samping sampai fungsinya perlu dipanggil.
Andy
Perhatikan bahwa modul selalu memiliki kode yang ketat, jadi selalu this === undefineddan Anda bahkan tidak perlu menyebutkan objek global
Bergi
22

Operator koma mengevaluasi setiap operannya (dari kiri ke kanan) dan mengembalikan nilai dari operan terakhir.

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

Jadi, mari kita lihat contoh:

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

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

Sekarang, dalam foometode, thissama dengan a(karena foodilampirkan ke a). Jadi jika Anda memanggil a.foo() secara langsung, itu akan masuk falseke konsol.

Tapi, jika Anda dipanggil (0, a.foo)(). Ekspresi ini (0, a.foo)akan mengevaluasi setiap operannya (dari kiri ke kanan) dan mengembalikan nilai dari operan terakhir. Dengan kata lain, (0, a.foo)setara dengan

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

Karena fungsi ini tidak lagi melekat pada apa pun, ini thisadalah objek global window. Itu sebabnya masuk truekonsol saat panggilan (0, a.foo)().

Huong Nguyen
sumber
berjalan console.log(this === window);di konsol dev tidak mencetak log lagi.
kushdilip
2
Ini sangat mengejutkan saya. Kuncinya di sini adalah bahwa operator Koma "mengembalikan nilai dari operan terakhir" - "nilai" di sini adalah fungsi itu sendiri tanpa induk yang memuatnya - jadi foo tidak lagi tinggal di dalam a.
martinp999