ค้นหาเว็บไซต์

ecmascript 6 - Javascript ES6 กำจัดการใช้คำสำคัญ 'this' ทุกที่ในคลาส


ฉันกำลังใช้ Traceur เพื่อที่จะสามารถเขียนจาวาสคริปต์ของอนาคตได้ตอนนี้ และนี่คือฟังก์ชันที่ฉันมีในบางคลาส

create() {
    this.game.physics.startSystem(Phaser.Physics.ARCADE);

    this.segmentcache = new SegmentCache(this.game);
    this.segments = new Segments(this.game);
    this.segments.cache = this.segmentcache;
    this.segments.seek(3);

    this.guy = new Guy(this.game, 140 + 8, 80);
    this.guy.anchor.set(0.5, 1.0);
    this.game.add.existing(this.guy);

    this.game.camera.x = 100;
    this.ticks = 0;
    this.cross = 0;
}

แน่นอน เหมือนกับโค้ดจาวาสคริปต์ดั้งเดิมใดๆ มันถูกครอบคลุมด้วยคำสำคัญ this อยู่ทั่วทุกที่ สำหรับคนที่มาจาก Java และภาษาใกล้เคียง มันไม่ค่อยเป็นธรรมชาติเหลือเกินสำหรับฉันที่ต้องระบุ this เมื่ออ้างถึงฟิลด์ภายในคลาส ในขณะที่ฉันไม่ได้ต้องทำแบบนั้น

มีวิธีใดบ้างที่จะทำให้ Traceur แปลความคลาสเหมือนกับ Java หรือไม่? (เช่น แทรก this อัตโนมัติเมื่อไม่ได้ระบุ เป็นต้น)

คำตอบ #1

เท่าที่ฉันทราบ ไม่มี

ในภาษา Java, C#, C++ เป็นต้น นี่เป็นคุณสมบัติของคอมไพเลอร์ ไม่ใช่ของการประมวลผล ซึ่งหมายความว่ามันถูกทำโดยอัตโนมัติ และสิ่งที่คอมไพเลอร์ทำคือการใส่ที่อยู่ที่ถูกต้องลงใน this และอ้างอิงตัวแปรในแบบที่ถูกต้อง มีข้อกำหนดในคอมไพเลอร์ส่วนใหญ่ว่า ถ้าคุณมีตัวแปรท้องถิ่น (ในขอบเขตท้องถิ่น) ที่มีชื่อเดียวกับตัวแปรสมาชิก ตัวแปรท้องถิ่นจะมีลำดับความสำคัญมากกว่า

ในขณะที่ใน JavaScript คุณสามารถแทนที่ this ได้อย่างง่ายดายผ่าน call, apply หรือ bind และทำให้ฟังก์ชันของคุณถูกเรียก กับ ออบเจ็กต์ซึ่งผู้เขียนไม่ได้ตั้งใจให้ทำงานด้วย (เช่น this อาจเป็นออบเจ็กต์ที่มีโครงสร้างต่างออกไป) และฉันคิดว่านี่คือเหตุผลที่ไวยากรณ์ของภาษาต้องการให้คุณระบุอย่างชัดเจนเสมอว่าคุณกำลังอ้างถึงสโคปหรือ this

ในร่างฟังก์ชันของ JavaScript จริง ๆ สามารถเข้าถึงสโคประดับโลกได้ ดังนั้นการกำหนด window.member (ถ้าในเบราว์เซอร์) อาจเปลี่ยนพฤติกรรมของฟังก์ชันของคุณได้ถ้าคุณไม่ใช้ this อย่างชัดเจน

คำตอบ #2

เท่าที่ฉันรู้ ไม่มีฟีเจอร์แบบนั้นใน ES6

คุณลักษณะประเภทนี้จะซับซ้อนขึ้นเนื่องจาก Javascript อนุญาตให้การอ้างอิงตัวแปรในขอบเขตของพ่อแม่ ดังนั้นจะต้องหาวิธีแยกแยะว่าบรรทัดของโค้ดเช่น:

ticks = 0;

หมายถึง

this.ticks = 0;

หรือว่ามันหมายถึงการอ้างถึงตัวแปรในสโคปปัจจุบันหรือตามสโคปของพาเรนต์โดยใช้ชื่อ ticks

การเพิ่มคุณสมบัติลงในวัตถุเพียงอย่างเดียวอาจทำให้โค้ดที่เคยทำงานได้ดีเกิดปัญหาโดยสร้างความขัดแย้งระหว่างการอ้างอิงคุณสมบัติและตัวแปรท้องถิ่นหรือตัวแปรในสโคปของพาเรนต์ที่มีชื่อเดียวกัน นั่นอาจทำให้เกิดความยุ่งเหยิง ตอนนี้คุณจะต้องตั้งชื่อสโคปให้ตัวแปรท้องถิ่นของคุณเพียงเพื่อหลีกเลี่ยงการเกิดความขัดแย้งกับชื่อคุณสมบัติ และถ้าคุณต้องตั้งสโคปให้ตัวแปรท้องถิ่น คุณเพิ่งนำชิ้นส่วนของไวยากรณ์เพิ่มขึ้นกลับมาอีกครั้งซึ่งคุณพยายามจะกำจัดออกไป

Java สามารถทนต่อสิ่งนี้ได้เพราะคอมไพเลอร์รู้ชื่อคุณสมบัติทั้งหมดล่วงหน้า ดังนั้นมันสามารถรายงานข้อผิดพลาดได้หากมีความขัดแย้ง JavaScript อนุญาตให้เพิ่มคุณสมบัติเพิ่มเติมได้แบบไดนามิก (เพิ่มได้ทุกเวลา) ดังนั้นตัวแยกวิเคราะห์ไม่ได้รู้จริง ๆ ว่าชื่อคุณสมบัติใดจะอยู่หรือไม่อยู่บนวัตถุใด ๆ ในเวลาที่ทำการวิเคราะห์ไวยากรณ์ ดังนั้นมันจึงไม่สามารถเตือนเกี่ยวกับความขัดแย้งได้ นี่เป็นความแตกต่างโดยธรรมชาติในการที่ภาษาทั้งสองทำการวิเคราะห์/คอมไพล์และทำงาน จึงนำไปสู่ความสามารถหรือข้อกำหนดที่แตกต่างกันในการเขียนโค้ด

สามารถใช้โครงสร้าง with เพื่อลดการพิมพ์บางส่วนได้ แต่ with กำลังถูกลบออกจาก Javascript (ไม่อนุญาตในโหมดเข้มงวด) ด้วยเหตุผลที่อธิบายไว้ที่นี่ ไม่ใช่เพื่อปรับปรุง ดังนั้นจึงไม่ใช่วิธีที่แนะนำ