Getters và setters cho các lớp ECMAScript 6 là gì?


102

Tôi đang bối rối không biết điểm của getters và setters là gì trong các lớp ECMAScript 6. Mục đích là gì? Dưới đây là một ví dụ mà tôi đang đề cập đến:

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
Nó tương tự như trong C #, nếu bạn tình cờ biết về nó.
Arturo Torres Sánchez


Bạn có thể tìm thấy bài viết hay giải thích điều này tại: coryrylan.com/blog/javascript-es6-class-syntax "Trong lớp của chúng tôi ở trên, chúng tôi có getter và setter cho thuộc tính name của chúng tôi. Chúng tôi sử dụng quy ước '_' để tạo trường hỗ trợ để lưu trữ thuộc tính name của chúng ta. Nếu không có điều này mỗi khi get hoặc set được gọi, nó sẽ gây ra tràn ngăn xếp "... Nó cũng nói về biến không thực sự là 'private', nhưng có rất nhiều cách mới để tạo private vars trong Các lớp JS; yêu thích của tôi chỉ được sử dụng nguyên cảo, nhưng tôi đã sử dụng cách tiếp cận Symbol quá
webdevinci

Câu trả lời:


108

Các setter và getter này cho phép bạn sử dụng các thuộc tính trực tiếp (không sử dụng dấu ngoặc đơn)

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

Điều này chỉ để thiết lập và nhận giá trị của thuộc tính.


1
Ý của bạn là thuộc tính thay vì thuộc tính? Chút bối rối đối với tôi
Krizzu

Tốt mắt, @Krizzu. Các thuộc tính tồn tại trong JavaScript và là những thứ hoàn toàn khác với các thuộc tính. Câu trả lời thực sự đề cập đến thuộc tính chứ không phải thuộc tính. Tôi đã chỉnh sửa câu trả lời. Tôi không nghĩ người trả lời sẽ phiền. :)
Ray Toal

Tôi không chắc đây thực sự là một lợi thế như vậy, bằng cách nào đó nó che giấu khái niệm sử dụng setters / getters. Khách hàng của một lớp có thể nghĩ rằng nó trực tiếp sử dụng các thuộc tính, nơi nó không áp dụng, nhưng tôi đồng ý rằng nó tuân thủ nguyên tắc ẩn thông tin / chi tiết. Có lẽ nếu chúng ta sử dụng điều này do đó, nó làm cho việc sử dụng dễ dàng hơn và tôi chỉ phải làm quen với nó nhiều hơn ...
Christof Kälin

Bạn có thể chuyển nhiều tham số trong một bộ định thời nếu vậy bạn sử dụng nó như thế nào? @ David Laberge
Vignesh S

Nếu bạn muốn tạo setters và getters theo cách thủ công, đây là một ví dụ điển hình từ coryrylan.com/blog/javascript-es6-class-syntax Đặt: set name(newName) { this._name = newName; }Nhận:get name() { return this._name.toUpperCase(); }
Jim Doyle

48

Getters và setters trong ES6 phục vụ cùng một mục đích mà chúng làm trong các ngôn ngữ khác ... bao gồm cả ES5. ES5 đã cho phép getters và setters thông qua Object.defineProperty, mặc dù chúng kém sạch sẽ và cồng kềnh hơn để sử dụng.

Một cách hiệu quả, getters và setters cho phép bạn sử dụng ký hiệu truy cập thuộc tính tiêu chuẩn để đọc và ghi trong khi vẫn có khả năng tùy chỉnh cách thuộc tính được truy xuất và biến đổi mà không cần các phương thức getter và setter rõ ràng.

Trong lớp Nhân viên ở trên, điều này có nghĩa là bạn có thể truy cập thuộc nametính như sau:

console.log(someEmployee.name);

trông giống như một quyền truy cập thuộc tính bình thường, nhưng nó thực sự sẽ gọi toUpperCasetên trước khi trả lại. Tương tự, làm điều này:

someEmployee.name = null;

sẽ truy cập setter, và nó sẽ không sửa đổi thuộc tính bên trong _namevì điều khoản bảo vệ được giới thiệu trong namesetter của.

Xem thêm câu hỏi chung Tại sao sử dụng getters và setters? để biết thêm thông tin về lý do tại sao có thể sửa đổi chức năng của quyền truy cập thành viên là hữu ích.


3

Bộ chuyển và bộ định tuyến ES6 có động cơ khác biệt đáng kể so với các khái niệm tương tự trong Java.

Trong Java, getters và setters cho phép một lớp định nghĩa một JavaBean. Điểm của getters và setters là nó cho phép bean có một "giao diện" hoàn toàn trực giao từ những trường công khai ngụ ý. Vì vậy, tôi có thể có một trường "tên" KHÔNG phải là thuộc tính JavaBean và tôi có thể có "địa chỉ" thuộc tính JavaBean KHÔNG phải là một trường.

Các thuộc tính của JavaBean cũng có thể được "khám phá" bởi hàng nghìn khuôn khổ (ví dụ: Hibernate) thông qua phản xạ Java. Do đó, getters và setters là một phần của phương pháp tiêu chuẩn để "phơi bày" các thuộc tính bean.

Getters và setters, là các hàm, cũng có giá trị mà chúng "trừu tượng hóa" việc triển khai. Nó có thể là một trường hoặc một giá trị được tính toán ("tổng hợp"). Vì vậy, nếu tôi có một thuộc tính bean được gọi là "mã zip", nó bắt đầu dưới dạng chuỗi được lưu trữ. Bây giờ, giả sử tôi muốn thay đổi nó thành một giá trị được tính từ địa chỉ / thành phố / tiểu bang?

Nếu tôi sử dụng một trường, mã này bị hỏng:

      String zipcode = address.zipcode();

Nhưng nếu tôi sử dụng getter, điều này không bị hỏng:

      String zipcode = address.getZipcode();

JavaScript không có bất cứ thứ gì giống như JavaBeans. Cho đến nay như tôi đã đọc, giá trị dự định của GET và SET được giới hạn trong các thuộc tính "tổng hợp" (tính toán) nói trên.

Nhưng nó tốt hơn java ở chỗ trong khi Java không cho phép bạn chuyển đổi tương thích một "trường" thành một phương thức, thì ES6 GET và SET cho phép điều đó.

Đó là, nếu tôi có:

       var zipcode = address.zipcode;

Nếu tôi thay đổi mã zip từ một thuộc tính đối tượng tiêu chuẩn thành một getter, thì đoạn mã trên bây giờ sẽ gọi hàm GET.

Lưu ý rằng nếu tôi không bao gồm GET trong định nghĩa, điều này sẽ KHÔNG gọi phương thức zipcode GET. Thay vào đó, nó sẽ chỉ gán mã zip của hàm cho var.

Vì vậy, tôi nghĩ đây là một số điểm khác biệt quan trọng để hiểu rõ hơn về bộ cài đặt và cài đặt Java và JavaScript ES6.


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

Dù sao gettersettercũng giống như một điệp viên. Nó theo dõi thuộc tính của một đối tượng, để bạn có thể làm điều gì đó, mỗi khi bạn lấy hoặc đặt giá trị của thuộc tính.

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.