2012-09-07 27 views
11

En Javascript, parece que el uso de acceso a propiedades no es tan común (a diferencia de otros lenguajes de OO como Java, por ejemplo).javascript acceso a propiedades

Si tengo un objeto Person con un nombre, definido como

function Person(name) { 
    this.name = name; 
} 

nombre de una persona no va a cambiar, pero yo quiero ser capaz de acceder a él cuando sea necesario, por lo que podía hacer algo como:

function Person(name) { 
    var name = name; 
    this.getName = function() { 
     return name; 
    } 
} 

Incluso en un lenguaje dinámico, creo que los principios de la utilización de captadores y definidores se aplican de la misma manera que lo hacen a mecanografiado estáticamente lenguajes orientados a objetos (por ejemplo, la encapsulación, la validación de la adición, la restricción de acceso, etc.)

Esta pregunta puede cerrarse como subjetiva, pero tengo curiosidad de por qué este comportamiento no aparece con más frecuencia (p. Los desarrolladores de Java se volverían locos si todo fuera público).

¿Existe una forma "estándar" de hacer esto en javascript? He visto Object.defineProperty, pero no todos los navegadores lo admiten.

+0

Supongo que podría estar relacionado parcialmente con el deseo de reducir las cargas de ancho de banda. Marcado adicional significa bits adicionales a través del cable. Si bien en el caso de un pequeño ejemplo como este, podría no parecer relevante, en una aplicación robusta que abarca decenas de miles de líneas, podría volverse significativo. – Shmiddty

+0

La definición adicional también significa el uso de memoria adicional en el cliente, en la misma línea que mi comentario anterior. – Shmiddty

+0

Creo que las respuestas ya dadas muestran que esta no es una buena pregunta para SO, ya que es propenso a obtener respuestas basadas en opiniones. – madth3

Respuesta

15

Javascript acceso de propiedad de intercepción-poder:

http://ejohn.org/blog/javascript-getters-and-setters/

mi humilde opinión esta es una solución mucho mejor para hacer cumplir el principio de acceso uniforme que más estrictos captadores explícitas de Java, sino que también es parte de la simplicidad y inflexibilidad de ese idioma (Groovy, por ejemplo, permite una intercepción similar).

+0

en la práctica, ¿esto se ve mucho? ¿O normalmente ve acceso directo a la propiedad? –

+0

Utilizaría el acceso directo a la propiedad a menos que necesite modificar la lógica de acceso: entonces usaría la interceptación. Puede que necesite preguntarse por qué usa getters y setters en Java si no hacen nada: cuál es la razón práctica real detrás de la doctrina de encapsulación. –

+0

A veces me pregunto por qué, particularmente en propiedades simples. Teóricamente, la idea es que si desea agregar algún otro comportamiento en el captador o instalador (por ejemplo, registro, validación, etc.). Pero en realidad, eso no ocurre con tanta frecuencia en las propiedades simples, así que es más una convención de Java (prefiero lo genial que es, donde no se declaran explícitamente los getters y setters, sino que se generan y se llaman automáticamente, pero le permite escribir la sintaxis del acceso directo a la propiedad). –

3

Creo que la respuesta es que emular clases en javascript no es una práctica común, porque el lenguaje es en realidad prototípico.

Aunque es posible crear estructuras de clase similar (como en su ejemplo), en realidad no son como las clases de Java, y como programador, termina peleando con los matices.

Sin embargo, si acepta la naturaleza prototípica de javascript, se verá recompensado por una estructura diferente, pero cohesiva y simple para el idioma.

No es necesario utilizar getters y setters con estructura prototípica, ya que puede simplemente establecer un objeto, bien, establecerlo en un valor, y obtenerlo, llamándolo como un valor.

Javascript no lo obliga a escribir código estructurado, y no le impide hacerlo. Creo que la cultura que se ha desarrollado en javascript ha desarrollado un buen estilo de codificación, que es perfectamente válido y diferente de cualquier otro idioma que use.

Sé que esta respuesta no es definitiva y concluyente, pero espero que haya algunas ideas que lo ayuden a encontrar la respuesta que está buscando.

+1

gracias. Podrías hacer lo mismo obtener/establecer valores directamente en Java (si hicieras las cosas públicas, por ejemplo), pero eso parece estar mal visto. Supongo que mucho de eso tiene que ver con en qué se han convertido las expresiones idiomáticas del idioma. –

+1

Un problema importante en Java es que no desea tener que cambiar la interfaz de su clase más adelante. Al ser un lenguaje compilado diseñado para el mantenimiento de códigos a largo plazo, las prioridades son diferentes a las de JS, un lenguaje basado en fuentes implementado en un entorno web que cambia rápidamente. –

7

Conozco mis pensamientos sobre el tema.

Getters y setters son malvados.

¡Espera! ¡De Verdad! Ten paciencia conmigo un momento y déjame explicarte.

Simplemente usando un método para obtener y establecer un valor es ... bueno .. un poco sin sentido. No protege, no realmente, y lo que pones es lo que obtienes.

Por otro lado, soy bastante aficionado a los métodos que colocan información, luego recupero la información. PERO aquí está la parte mágica! No es la misma información. No directamente.

function Person(name) { 
    this.getFullName = function() {return this.firstName + " " + this.lastName;}; 
    this.setBirthday = function(date) { this.birthday = date; }; 

    this.getAge = function() { /* Return age based on the birthday */ }; 
    this.isOfLegalDrinkingAge function() { /* do your math here too */ }; 
} 

Pero la mayor parte del tiempo estoy empujando datos estáticos y obteniendo datos estáticos. ¿Cuál es el sentido de esconderlo detrás de getters y setters?

Como una razón secundaria, al tratar con DOM y la mayoría de los objetos host, establece propiedades. No juegas con getters y setters. No usarlos se ajusta al resto del 'sabor' de lo que hacen los codificadores JS.

+0

@BillyMoon - Se pregunta si puede cambiar su nombre de usuario a "Javascript Preacher" –

+0

Gracias por la explicación. Creo que el hecho de que no es el "sabor" de javascript es realmente lo que estaba obteniendo aquí. –

+0

Mi problema con esto es preguntarse si las cosas son funciones o propiedades. A veces puede parecer bastante arbitrario. Person.firstName funciona, pero Person.firstName() no lo hace, mientras que por el contrario necesito utilizar Person.fullName() en lugar de Person.fullName ... – CuddleBunny

0

Me disculpo si no entiendo la pregunta correctamente, pero las funciones de auto de ejecución son una manera de hacer que los miembros del público/privado

var Person = function(){ 
    var _name = "Roger", 
     self = { getName : function(){ return _name; }}; 
    return self; 
}() 

A continuación, puede acceder Person.getName() desde cualquier lugar, pero no establecer _name .

+1

Sé que eres capaz de hacer esto, parece que no es una práctica común ... –

1

Esto es lo que he usado para campos locales:

TYPE_DEFAULT_VALUE= { 
    number: 0, 
    string: "", 
    array: [], 
    object: {}, 
}; 

typeOf = function (object) { 
    if (typeof object === "number" && isNaN(object)) 
     return NaN; 
    try { 
     return Object.prototype.toString.call(object).slice(8, -1).toLowerCase(); 
    } 
    catch(ex) { 
     return "N/A"; 
    }; 
}; 

getAccessor = function(obj, key, type, defaultValue) { 
    if (defaultValue === undefined) 
     defaultValue = TYPE_DEFAULT_VALUE[type] === undefined ? null : TYPE_DEFAULT_VALUE[type]; 
    return { 
     enumerable: true, 
     configurable: true, 
     get: function() { 
      if (obj[key] === undefined) 
       obj[key] = defaultValue; 
      return obj[key]; 
     }, 
     set: function (value) { 
      if (typeOf(value) === type) 
       obj[key] = value; 
     }, 
    }; 
} 

LocalFields = function (fields, object) { 
    /** 
    * field properties 
    * { 
    * type: [ required ] (number | string | array | object | ...), 
    * defaultValue: [ optional ] 
    * } 
    */ 
    if (! fields) 
     throw "Too few parameters ..."; 
    if (! object) 
     object = this; 

    var obj = this; 
    var fieldsAccessor = {}; 
    for(key in fields){ 
     field = fields[key]; 
     fieldHandler = key[0].toUpperCase() + key.substr(1); 
     if(! field.type) 
      throw "Type not set for field: " + key; 

     fieldsAccessor[fieldHandler] = getAccessor(obj, fieldHandler, field.type, field.defaultValue) 
    } 
    Object.defineProperties(object, fieldsAccessor); 
} 

Ahora para cada clase que sólo puede llamar algo así como:

Person = function(){ 
    new LocalFields({ 
     id:  { type: "number" }, 
     name: { type: "string" }, 
    }, this); 
} 

Y entonces, como VS get y set que vas a llamar:

var alex = new Person(); 
alex.Name = "Alex Ramsi"; 
console.clear(); 
console.info(alex.Name); 
Cuestiones relacionadas