getters และ setters สำหรับคลาส ECMAScript 6 คืออะไร?


102

ฉันสับสนว่าจุดของ getters และ setters ในคลาส ECMAScript 6 คืออะไร จุดประสงค์คืออะไร? ด้านล่างนี้เป็นตัวอย่างที่ฉันอ้างถึง:

class Employee {

    constructor(name) {
        this._name = name;
    }

    doWork() {
        return `${this._name} is working`;
    }

    get name() {
        return this._name.toUpperCase();
    }

    set name(newName){
        if(newName){ 
            this._name = newName;
        }
    }
}

1
มันคล้ายกับใน C # ถ้าคุณรู้เกี่ยวกับมัน
Arturo Torres Sánchez


บทความดีๆที่อธิบายเรื่องนี้สามารถพบได้ที่: coryrylan.com/blog/javascript-es6-class-syntax "ในชั้นเรียนของเราด้านบนเรามี getter และ setter สำหรับคุณสมบัติ name ของเราเราใช้อนุสัญญา '_' เพื่อสร้างฟิลด์สำรอง เพื่อจัดเก็บคุณสมบัติชื่อของเราหากไม่ใช้สิ่งนี้ทุกครั้งที่ get หรือ set ถูกเรียกมันจะทำให้เกิด stack overflow "... นอกจากนี้ยังพูดถึงตัวแปรที่ไม่ได้เป็น 'private' อย่างแท้จริง แต่มีวิธีใหม่ ๆ มากมายในการสร้าง private vars ใน คลาส JS; สิ่งที่ฉันชอบคือแค่ใช้ typescript แต่ฉันก็ใช้วิธี Symbol เหมือนกัน
webdevinci

คำตอบ:


108

ตัวตั้งค่าและตัวรับเหล่านี้ช่วยให้คุณใช้คุณสมบัติได้โดยตรง (โดยไม่ต้องใช้วงเล็บ)

var emp = new Employee("TruMan1");

if (emp.name) { 
  // uses the get method in the background
}

emp.name = "New name"; // uses the setter in the background

นี่เป็นเพียงการตั้งค่าและรับมูลค่าของคุณสมบัติเท่านั้น


1
คุณหมายถึงคุณสมบัติแทนแอตทริบิวต์หรือไม่? สับสนเล็กน้อยสำหรับฉัน
Krizzu

ตาดี @Krizzu. แอตทริบิวต์มีอยู่ใน JavaScript และแตกต่างจากคุณสมบัติอย่างสิ้นเชิง คำตอบนั้นอ้างถึงคุณสมบัติไม่ใช่แอตทริบิวต์ ฉันได้แก้ไขคำตอบแล้ว ฉันไม่คิดว่าผู้ตอบจะรังเกียจ :)
Ray Toal

ฉันไม่ค่อยแน่ใจว่านี่เป็นข้อได้เปรียบจริงๆมันซ่อนแนวคิดของการใช้ setters / getters ไคลเอนต์ของคลาสอาจคิดว่ามันใช้คุณสมบัติโดยตรงโดยที่มันไม่เหมาะสม แต่ฉันยอมรับว่ามันเป็นไปตามหลักการซ่อนข้อมูล / รายละเอียด บางทีถ้าเราใช้มันทำให้การใช้งานง่ายขึ้นและฉันก็ต้องคุ้นเคยกับมันมากขึ้น ...
Christof Kälin

คุณสามารถส่งผ่านพารามิเตอร์หลายตัวใน setter ได้หรือไม่ถ้าคุณใช้มันอย่างไร? @David Laberge
Vignesh S

หากคุณต้องการสร้าง setters และ getters ด้วยตนเองนี่คือตัวอย่างที่ดีจากcoryrylan.com/blog/javascript-es6-class-syntax Set: set name(newName) { this._name = newName; }Get:get name() { return this._name.toUpperCase(); }
Jim Doyle

48

ตัวรับและตัวตั้งค่าใน ES6 มีจุดประสงค์เดียวกับที่ทำในภาษาอื่น ๆ ... รวมถึง ES5 ES5 ช่วยให้ getters และ setters ผ่านได้Object.definePropertyแล้วแม้ว่าจะสะอาดน้อยกว่าและใช้งานยากกว่า

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

ในชั้นพนักงานข้างต้นหมายความว่าคุณสามารถเข้าถึงnameคุณสมบัติดังนี้:

console.log(someEmployee.name);

มันจะดูเหมือนการเข้าถึงทรัพย์สินตามปกติ แต่จริงๆแล้วมันจะเรียกtoUpperCaseชื่อก่อนที่จะส่งคืน ในทำนองเดียวกันการทำเช่นนี้:

someEmployee.name = null;

จะเข้าถึง setter และจะไม่แก้ไข_nameคุณสมบัติภายในเนื่องจากคำสั่ง guard ที่แนะนำในnamesetter ของ

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


3

ตัวรับและตัวตั้งค่า ES6 มีแรงจูงใจที่แตกต่างกันอย่างมากจากแนวคิดที่คล้ายกันใน Java

ใน Java getters และ setters อนุญาตให้คลาสกำหนด JavaBean จุดสำคัญของ getters และ setters คือการอนุญาตให้ bean มี "ส่วนต่อประสาน" ที่ตั้งฉากกันอย่างสมบูรณ์จากที่โดยนัยของฟิลด์สาธารณะ ดังนั้นฉันสามารถมีฟิลด์ "ชื่อ" ที่ไม่ใช่คุณสมบัติ JavaBean และฉันสามารถมี "ที่อยู่" คุณสมบัติ JavaBean ที่ไม่ใช่ฟิลด์

คุณสมบัติ JavaBean ยัง "ค้นพบได้" โดยเฟรมเวิร์กหลายพันเฟรม (ตัวอย่างเช่นไฮเบอร์เนต) ผ่านการสะท้อนของ Java ดังนั้นตัวรับและตัวตั้งค่าจึงเป็นส่วนหนึ่งของวิธีมาตรฐานในการ "เปิดเผย" คุณสมบัติของถั่ว

ตัวรับและตัวเซ็ตซึ่งเป็นฟังก์ชันก็มีค่าที่พวกเขา "นามธรรม" ในการนำไปใช้งาน อาจเป็นทั้งฟิลด์หรือค่า ("สังเคราะห์") ที่คำนวณได้ ดังนั้นถ้าฉันมีคุณสมบัติ bean ที่เรียกว่า "zipcode" ซึ่งจะเริ่มต้นเป็นสตริงที่เก็บไว้ ตอนนี้สมมติว่าฉันต้องการเปลี่ยนเป็นค่าที่คำนวณจากที่อยู่ / เมือง / รัฐ?

หากฉันใช้ฟิลด์รหัสนี้จะแบ่ง:

      String zipcode = address.zipcode();

แต่ถ้าฉันใช้ getter สิ่งนี้จะไม่ทำลาย:

      String zipcode = address.getZipcode();

JavaScript ไม่มีอะไรเหมือน JavaBeans เท่าที่ฉันอ่านมาค่าที่ตั้งใจไว้ของ GET และ SET ถูก จำกัด ไว้ที่คุณสมบัติ "สังเคราะห์" (คำนวณ) ข้างต้น

แต่ค่อนข้างดีกว่า java ในขณะที่ Java ไม่อนุญาตให้คุณแปลง "เขตข้อมูล" เป็นวิธีการที่เข้ากันได้ ES6 GET และ SET ช่วยให้สามารถทำได้

นั่นคือถ้าฉันมี:

       var zipcode = address.zipcode;

ถ้าฉันเปลี่ยนรหัสไปรษณีย์จากการเป็นคุณสมบัติออบเจ็กต์มาตรฐานเป็น getter ตอนนี้โค้ดด้านบนจะเรียกฟังก์ชัน GET

โปรดทราบว่าหากฉันไม่ได้รวม GET ไว้ในคำจำกัดความสิ่งนี้จะไม่เรียกใช้เมธอด GET รหัสไปรษณีย์ แต่จะเป็นเพียงการกำหนดรหัสไปรษณีย์ของฟังก์ชันให้กับ var

ดังนั้นฉันคิดว่าสิ่งเหล่านี้เป็นความแตกต่างที่สำคัญในการทำความเข้าใจระหว่าง Java และ JavaScript ES6 getters และ setters


0
class Employee {

    constructor(name) {
      this._name = name;
    }

    doWork() {
      return `${this._name} is working`;
    }

    get name() {
      // when you get this by employeeInstance.mame
      // the code below will be triggered
      // and you can do some logic here
      // just like `console.log` something you want
      console.log('get triggered!')
      return this._name.toUpperCase();
    }

    set name(newName) {
      // the same as `get`
      // when you employeeInstance.mame = 'xxx'
      // the code blew will be trigged
      // and you can also do some logic 
      // like here is a `console.log` and `if check`
      console.log('set triggered!')
      if (newName) {
        this._name = newName;
      }
    }
  }

  const employeeInstance = new Employee('mike')
  employeeInstance.name
  employeeInstance.name = '' // this won't be success, because the `if check`
  console.log(employeeInstance.name)

  // => 
  // get triggered
  // set triggered
  // get triggered
  // MIKE

อย่างไรก็ตามgetterและsetterเป็นเหมือนสายลับ มันสอดแนมคุณสมบัติของวัตถุเพื่อให้คุณสามารถทำบางสิ่งได้ทุกครั้งที่คุณได้รับหรือกำหนดมูลค่าของคุณสมบัติ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.