¿Para qué sirven los getters y setters en las clases de ECMAScript 6?

102

Estoy confundido en cuanto a cuál es el punto de los getters y setters en las clases de ECMAScript 6. ¿Cuál es el propósito? A continuación se muestra un ejemplo al que me refiero:

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;
        }
    }
}
TruMan1
fuente
1
Es similar a los de C #, si lo conoce.
Arturo Torres Sánchez
Se puede encontrar un buen artículo que explica solo esto en: coryrylan.com/blog/javascript-es6-class-syntax "En nuestra clase anterior tenemos un getter y setter para nuestra propiedad de nombre. Usamos la convención '_' para crear un campo de respaldo para almacenar nuestra propiedad de nombre. Sin esto, cada vez que se llame a get o set, se produciría un desbordamiento de pila "... También habla de que la variable no es realmente 'privada', pero hay numerosas formas nuevas de crear vars privadas en Clases JS; mi favorito es solo usar TypeScript, pero también he usado el enfoque de Symbol
webdevinci

Respuestas:

108

Estos setter y getter le permiten usar las propiedades directamente (sin usar el paréntesis)

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

Esto es solo para establecer y obtener el valor de la propiedad.

David Laberge
fuente
1
¿Quiso decir propiedad en lugar de atributo? Un poco confuso para mí
Krizzu
Buen ojo, @Krizzu. Los atributos existen en JavaScript y son cosas completamente diferentes a las propiedades. De hecho, la respuesta se refiere a propiedades y no a atributos. Edité la respuesta. No creo que al respondedor le importe. :)
Ray Toal
No estoy muy seguro de que esto sea realmente una ventaja, de alguna manera oculta la noción de usar setters / getters. Un cliente de una clase puede pensar que usa propiedades directamente, donde no es apropiado, pero estoy de acuerdo en que se adhiere al principio de ocultación de información / detalles. Tal vez si usamos esto, en consecuencia, facilita el uso y solo tengo que acostumbrarme más ...
Christof Kälin
¿Puede pasar múltiples parámetros en un setter? Si es así, ¿cómo lo usa? @David Laberge
Vignesh S
Si desea crear setters y getters manualmente, aquí tiene un buen ejemplo de coryrylan.com/blog/javascript-es6-class-syntax Set: set name(newName) { this._name = newName; }Get:get name() { return this._name.toUpperCase(); }
Jim Doyle
48

Los getters y setters en ES6 tienen el mismo propósito que en otros idiomas ... incluido ES5. ES5 ya permite getters y setters a través Object.defineProperty, aunque son menos limpios y más engorrosos de usar.

Efectivamente, los captadores y definidores le permiten utilizar la notación de acceso a la propiedad estándar para lecturas y escrituras, al mismo tiempo que tiene la capacidad de personalizar cómo se recupera y modifica la propiedad sin los métodos de captador y definidor explícitos necesarios.

En la clase de Empleado anterior, esto significaría que podría acceder a la namepropiedad de esta manera:

console.log(someEmployee.name);

Sería mirar como un acceso a la propiedad normal, pero en realidad se llamaría toUpperCaseen el nombre antes de devolverlo. Del mismo modo, haciendo esto:

someEmployee.name = null;

accedería al setter, y no modificaría la _namepropiedad interna debido a la cláusula de guardia introducida en nameel setter.

Consulte también la pregunta general ¿ Por qué utilizar getters y setters? para obtener más información sobre por qué es útil poder modificar la funcionalidad del acceso de miembros.

Alexis Rey
fuente
3

Los captadores y definidores de ES6 tienen una motivación sustancialmente diferente a conceptos similares en Java.

En Java, los getters y setters permiten que una clase defina un JavaBean. El punto de los getters y setters es que permite que el bean tenga una "interfaz" completamente ortogonal de la que implican los campos públicos. Entonces puedo tener un "nombre" de campo que NO sea una propiedad de JavaBean, y puedo tener una "dirección" de propiedad de JavaBean que NO sea un campo.

Las propiedades de JavaBean también son "detectables" por miles de marcos (Hibernate, por ejemplo) a través de la reflexión de Java. Por tanto, los captadores y definidores son parte de un método estándar para "exponer" las propiedades de los frijoles.

Los getters y setters, al ser funciones, también tienen el valor de "abstraer" la implementación. Puede ser O un campo o un valor calculado ("sintético"). Entonces, si tengo una propiedad de frijol llamada "código postal", comienza como una cadena almacenada. Ahora suponga que quiero cambiarlo para que sea un valor calculado a partir de la dirección / ciudad / estado.

Si uso un campo, este código se rompe:

      String zipcode = address.zipcode();

Pero si uso un captador, esto no se rompe:

      String zipcode = address.getZipcode();

JavaScript no tiene nada parecido a JavaBeans. Hasta donde he leído, el valor previsto de GET y SET se limita a las propiedades "sintéticas" (calculadas) mencionadas anteriormente.

Pero es algo mejor que Java en el sentido de que, si bien Java no le permite convertir de manera compatible un "campo" en un método, ES6 GET y SET lo permite.

Es decir, si tengo:

       var zipcode = address.zipcode;

Si cambio el código postal de ser una propiedad de objeto estándar a un captador, el código anterior ahora llama a la función GET.

Tenga en cuenta que si no incluyo GET en la definición, esto NO invocaría el método GET del código postal. En cambio, simplemente asignaría el código postal de la función a var.

Así que creo que estas son algunas distinciones importantes para entender entre los getters y setters de Java y JavaScript ES6.

DaBlick
fuente
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

De todos modos el gettery setteres como un espía. Espía la propiedad de un objeto, de modo que usted puede hacer algo cada vez que obtiene o establece el valor de la propiedad.

RandomYang
fuente