เหตุใด babel จึงเขียนฟังก์ชันที่นำเข้าใหม่เรียกไปที่ (0, fn) (…)


102

ให้ไฟล์อินพุตเช่น

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

@Bergi ฉันแน่ใจว่าเหตุผลที่พวกเขาใช้ (0,) คือเพื่อประหยัดพื้นที่ในรหัสที่โปร่งใส
Andy


คำตอบ:


141

(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
ขอบคุณสำหรับลิงค์ ผ่านมาหลายครั้งและในที่สุดก็ตัดสินใจค้นหาว่าเกิดอะไรขึ้น
theflowersoftime

@RobW ฉันคิดว่าการเพิ่มvar _a = (0, _b.a)ที่ด้านบนของไฟล์จากนั้นการโทร_aจะช่วยประหยัดพื้นที่ได้มากขึ้นในหลาย ๆ กรณีความคิดที่พวกเขาไม่ได้ทำเช่นนั้น?
Andy

1
@Andy ข้อเสนอแนะของคุณอาจมีผลข้างเคียงเช่นเมื่อ_b.aเป็น (ไดนามิก) getter
Rob W

@ RobW ฉันเห็นดังนั้นคุณกำลังพูดถึงแนวคิดคือการหลีกเลี่ยงผลข้างเคียงที่อาจเกิดขึ้นจนกว่าจะต้องเรียกใช้ฟังก์ชัน
Andy

โปรดสังเกตว่าโมดูลเป็นรหัสที่เข้มงวดเสมอดังนั้นจึงเป็นเช่นนั้นเสมอthis === undefinedและคุณไม่จำเป็นต้องพูดถึง global object ด้วย
ซ้ำ

24

ตัวดำเนินการลูกน้ำจะประเมินแต่ละตัวถูกดำเนินการ (จากซ้ายไปขวา) และส่งคืนค่าของตัวถูกดำเนินการสุดท้าย

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);ในคอนโซล dev จะไม่พิมพ์บันทึกอีกต่อไป
kushdilip

3
สิ่งนี้ทำให้ฉันรู้สึกแย่ กุญแจสำคัญในที่นี้คือตัวดำเนินการ Comma "ส่งกลับค่าของตัวถูกดำเนินการสุดท้าย" - "ค่า" ในที่นี้คือฟังก์ชันนั้นไม่มีพาเรนต์ที่มีอยู่ดังนั้น foo จะไม่อยู่ภายในตัวถูกดำเนินการอีกต่อไป
martinp999
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.