Tại sao babel viết lại hàm đã nhập gọi đến (0, fn) (…)?


100

Đưa ra một tệp đầu vào như

import { a } from 'b';

function x () {
  a()
}

babel sẽ biên dịch nó thành

'use strict';

var _b = require('b');

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

nhưng khi được biên dịch ở chế độ rời, lệnh gọi hàm được xuất ra dưới dạng _b.a();

Tôi đã thực hiện một số nghiên cứu về nơi toán tử dấu phẩy được thêm vào với hy vọng có một nhận xét giải thích nó. Mã chịu trách nhiệm thêm nó ở đây .


4
Họ nên làm _b.a.call()cho ý định rõ ràng.
Bergi

@Bergi Tôi chắc rằng lý do họ đặt nó với (0,) là để tiết kiệm dung lượng trong mã đã chuyển.
Andy


Câu trả lời:


138

(0, _b.a)()đảm bảo rằng hàm _b.ađược gọi với thisđặt thành đối tượng toàn cục (hoặc nếu chế độ nghiêm ngặt được bật, thành undefined). Nếu bạn gọi _b.a()trực tiếp, thì _b.asẽ được gọi với thisđặt thành_b .

(0, _b.a)(); tương đương với

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

( ,là toán tử dấu phẩy, xem https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator ).


3
Cảm ơn các liên kết. đã trải qua điều này rất nhiều lần và cuối cùng quyết định tìm hiểu điều gì đang xảy ra.
theflowersoftime

@RobW Tôi nghĩ rằng việc thêm var _a = (0, _b.a)ở đầu tệp và sau đó gọi _asẽ tiết kiệm thêm dung lượng trong nhiều trường hợp, bất kỳ ý tưởng nào mà họ không làm điều đó?
Andy

1
@Andy Đề xuất của bạn có thể có tác dụng phụ, ví dụ: khi nào _b.alà một cơn sốt (động).
Rob W

@RobW Tôi hiểu rồi, vì vậy bạn đang nói đến ý tưởng là tránh các tác dụng phụ tiềm ẩn cho đến khi hàm cần được gọi.
Andy

Chú ý rằng các module luôn mã nghiêm ngặt, vì vậy nó luôn luôn this === undefinedvà bạn thậm chí không cần phải đề cập đến đối tượng toàn cầu
Bergi

22

Toán tử dấu phẩy đánh giá từng toán hạng của nó (từ trái sang phải) và trả về giá trị của toán hạng cuối cùng.

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

Vì vậy, hãy xem một ví dụ:

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

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

Bây giờ, trong foophương thức, thislà bằng a(bởi vì foođược gắn vào a). Vì vậy, nếu bạn gọia.foo( ) trực tiếp, nó sẽ đăng nhập falsebảng điều khiển.

Nhưng, nếu bạn được gọi (0, a.foo)(). Biểu thức (0, a.foo)sẽ đánh giá từng toán hạng của nó (từ trái sang phải) và trả về giá trị của toán hạng cuối cùng. Nói cách khác, (0, a.foo)tương đương với

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

Vì hàm này không còn được gắn với bất cứ thứ gì, nên nó thislà đối tượng toàn cục window. Đó là lý do tại sao nó đăng nhập truebảng điều khiển khi cuộc gọi (0, a.foo)().


đang chạy console.log(this === window);trong bảng điều khiển dành cho nhà phát triển sẽ không in nhật ký nữa.
kushdilip

2
Điều này đã thổi vào tâm trí tôi. Chìa khóa ở đây là toán tử Dấu phẩy "trả về giá trị của toán hạng cuối cùng" - "giá trị" ở đây là bản thân hàm không có cha chứa nó - vì vậy foo không còn tồn tại bên trong a.
martinp999 Ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.