วิธีการในวัตถุ ES6: การใช้ฟังก์ชันลูกศร


96

ใน ES6 ทั้งสองอย่างนี้ถูกกฎหมาย:

var chopper = {
    owner: 'Zed',
    getOwner: function() { return this.owner; }
};

และเป็นชวเลข:

var chopper = {
    owner: 'Zed',
    getOwner() { return this.owner; }
}

เป็นไปได้ไหมที่จะใช้ฟังก์ชั่นลูกศรใหม่ด้วย ในการลองทำสิ่งต่างๆเช่น

var chopper = {
    owner: 'John',
    getOwner: () => { return this.owner; }
};

หรือ

var chopper = {
    owner: 'John',
    getOwner: () => (this.owner)
};

ฉันได้รับข้อความแสดงข้อผิดพลาดที่บอกว่าวิธีนี้ไม่สามารถเข้าถึงthisได้ นี่เป็นเพียงปัญหาทางไวยากรณ์หรือคุณไม่สามารถใช้วิธีการท่อไขมันภายในวัตถุ ES6 ได้หรือไม่?


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

1
ในขณะที่ใช้ไวยากรณ์ fat arrow? เฉพาะในกรณีที่คุณแก้ไขthisค่าโดยการสร้างchopperวัตถุก่อนจากนั้นทำการกำหนดในฟังก์ชันที่thisชี้ไปที่วัตถุนั้น สิ่งนี้สามารถทำได้อย่างหมดจดด้วยฟังก์ชันตัวสร้าง

1
การสาธิตนี้จะทำงานใน Firefox Chrome ยังไม่มี jsfiddle.net/bfyarxfe

2
@fox คุณต้องใช้ 'ใช้อย่างเข้มงวด' บน jsfiddle นั้น
Walter Chapilliquen - wZVanG

1
@fox: ทำงานได้ดีในสภาพแวดล้อมที่รองรับ Firefox ยังไม่มีการสนับสนุนที่สมบูรณ์ ลองใช้ในContinuumและconsole.log()ผลของการเรียกใช้เมธอด มันได้ผล.

คำตอบ:


154

ฟังก์ชั่น Arrow ไม่ได้ออกแบบมาเพื่อใช้ในทุกสถานการณ์เพียง แต่เป็นฟังก์ชันที่ล้าสมัยในเวอร์ชันที่สั้นกว่าเท่านั้น ไม่ได้มีวัตถุประสงค์เพื่อแทนที่ไวยากรณ์ของฟังก์ชันโดยใช้functionคีย์เวิร์ด กรณีการใช้งานที่พบบ่อยที่สุดสำหรับฟังก์ชันลูกศรคือ "lambdas" สั้น ๆ ซึ่งไม่ได้กำหนดนิยามใหม่thisมักใช้เมื่อส่งผ่านฟังก์ชันเป็นการเรียกกลับไปยังฟังก์ชันบางฟังก์ชัน

ไม่สามารถใช้ฟังก์ชันลูกศรเพื่อเขียนเมธอดอ็อบเจ็กต์ได้เนื่องจากอย่างที่คุณพบเนื่องจากฟังก์ชันลูกศรปิดทับthisบริบทที่ปิดด้วยคำศัพท์thisลูกศรภายในคือสิ่งที่เป็นปัจจุบันที่คุณกำหนดอ็อบเจ็กต์ ซึ่งจะกล่าวว่า:

// Whatever `this` is here...
var chopper = {
    owner: 'Zed',
    getOwner: () => {
        return this.owner;    // ...is what `this` is here.
    }
};

ในกรณีของคุณต้องการเขียนวิธีการบนวัตถุคุณควรใช้functionไวยากรณ์แบบดั้งเดิมหรือไวยากรณ์วิธีการที่แนะนำใน ES6:

var chopper = {
    owner: 'Zed',
    getOwner: function() {
        return this.owner;
    }
};

// or

var chopper = {
    owner: 'Zed',
    getOwner() {
        return this.owner;
    }
};

(มีความแตกต่างเล็กน้อยระหว่างกัน แต่จะสำคัญก็ต่อเมื่อคุณใช้superในgetOwnerสิ่งที่คุณไม่ได้เป็นหรือถ้าคุณคัดลอกgetOwnerไปยังวัตถุอื่น)

มีบางคนโต้แย้งในรายการ ES6 ทางเกี่ยวกับการบิดในฟังก์ชั่นที่มีลูกศรไวยากรณ์ที่คล้ายกัน thisแต่มีของตัวเองเป็น อย่างไรก็ตามข้อเสนอนี้ได้รับการตอบรับที่ไม่ดีเนื่องจากเป็นเพียงน้ำตาลทางไวยากรณ์ทำให้ผู้ใช้สามารถบันทึกการพิมพ์ไม่กี่อักขระและไม่มีฟังก์ชันการทำงานใหม่ใด ๆ เหนือไวยากรณ์ของฟังก์ชันที่มีอยู่ โปรดดูที่หัวข้อฟังก์ชั่นลูกศรไม่ได้ผูกไว้


หากฉันอ่านสิ่งนี้อย่างถูกต้องดูเหมือนว่าจะแนะนำว่ารายชื่ออีเมลจะจัดลำดับความสำคัญของน้ำตาลในการสังเคราะห์แม้ว่าจะทำให้โค้ดมีความสม่ำเสมอ / อ่านได้ง่ายขึ้นก็ตาม ตามที่กล่าวมาการใช้ฟังก์ชัน fat-arrow ในบริบท OOP ภายใต้ ES6 มีความท้าทายมากกว่าการพูดภายใต้ Coffeescript
จิ้งจอก

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

12

ในบรรทัดนี้getOwner: => (this.owner)ควรเป็น:

var chopper = {
    owner: 'John',
    getOwner: () => this.owner
}; //here `this` refers to `window` object.

คุณจะต้องประกาศthisเป็นฟังก์ชัน:

var chopper = {
    owner: 'John',
    getOwner() { return this.owner }
};

หรือ:

var chopperFn = function(){

    this.setOwner = (name) => this.owner = name;
    Object.assign(this,{
        owner: 'Jhon',
        getOwner: () => this.owner,
    })

}

var chopper = new chopperFn();
console.log(chopper.getOwner());
chopper.setOwner('Spiderman');
console.log(chopper.getOwner());


1
ฉันได้รับข้อผิดพลาดที่นี่:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox

ฉันเห็นว่ามันเป็นการใช้งานที่ถูกต้องอย่างไรก็ตามวิธีการ esta จะส่งกลับหน้าต่าง Object เสมอ คุณจะต้องประกาศthisภายในฟังก์ชัน
Walter Chapilliquen - wZVanG

2
thiswindowไม่จำเป็นต้องหมายถึง หมายถึงค่าปัจจุบันของสิ่งใดก็ตามที่thisอยู่ในสภาพแวดล้อมที่ปิดล้อมซึ่งอาจเป็นหรือไม่windowก็ได้ บางทีนั่นอาจเป็นสิ่งที่คุณหมายถึง แค่ต้องการให้แน่ใจว่าเขาเข้าใจว่ามันไม่ใช่ค่าเริ่มต้นบางอย่าง

@torazaburo ไม่เป็นไรสำหรับฉันฉันลองthisแล้วตอนนี้อ้างถึงคลาส
Walter Chapilliquen - wZVanG

2
สิ่งที่คุณเขียนจะเทียบเท่ากับการ var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }แต่อย่างละเอียดกว่าเพียงแค่เขียน

1

เคล็ดลับสั้น ๆ ที่ฉันทำตามเพื่อใช้ฟังก์ชันลูกศร

  • ใช้ฟังก์ชันที่ไม่ใช่ลูกศรสำหรับวิธีการที่จะใช้object.method()ไวยากรณ์ (เป็นฟังก์ชันที่จะได้รับคุณค่าที่มีความหมายthisจากผู้โทร)
  • ใช้ฟังก์ชันลูกศรสำหรับเกือบทุกอย่าง

0

ฟังก์ชันลูกศรภายในนี้ไม่สะท้อนบริบทของวัตถุ แต่จะให้บริบทที่เรียกวิธีวัตถุ

ตรวจสอบสิ่งนี้สิ่งนี้จะให้ข้อมูลเชิงลึกเกี่ยวกับเวลาที่ควรใช้ลูกศรและเมื่อไม่ https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/


0

ถ้าคุณมีฟังก์ชั่นการใช้ลูกศรคุณสามารถเปลี่ยนthisไปchopper,

var chopper = {
  owner: "John",
  getOwner: () => chopper.owner
};

แม้ว่านี่จะไม่ใช่แนวทางปฏิบัติที่ดีที่สุด แต่เมื่อคุณเปลี่ยนชื่อวัตถุคุณต้องเปลี่ยนฟังก์ชันลูกศรนี้


0

เคล็ดลับอีกประการหนึ่งในโหมดเข้มงวดthisยังคงอ้างถึง Window แทนที่จะไม่ได้กำหนด

  (() => {
    "use strict";
    console.log(this); // window
  })();

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.