2009-06-15 16 views
35

Resumen breve: Estoy en una situación en la que me gustaría obtener un getter estilo PHP, pero en JavaScript.Obtención de JavaScript para todas las propiedades

Mi JavaScript se ejecuta solo en Firefox, así que el JS específico de Mozilla está bien para mí.

La única manera en que puedo encontrar para hacer un captador JS requiere especificar su nombre, pero me gustaría definir un captador de todos los nombres posibles. No estoy seguro si esto es posible, pero me gustaría saberlo.

+6

me imagino que se refiere a las funciones mágicas __get y __set – seanmonstar

Respuesta

44

Lo más parecido que puedes encontrar es __noSuchMethod__, que es el equivalente de JavaScript de __call() de JavaScript.

Desafortunadamente, no hay un equivalente de __get/__ set, porque con ellos podríamos haber implementado __noSuchMethod__, pero aún no veo una manera de implementar propiedades (como en C#) usando __noSuchMethod__.

var foo = { 
    __noSuchMethod__ : function(id, args) { 
     alert(id); 
     alert(args); 
    } 
}; 

foo.bar(1, 2); 
+1

En realidad, estaba tratando de crear un equivalente de "mensaje que no come nada", ¡y esto lo hace * exactamente *! ¡Gracias! – arantius

+0

No tenía idea sobre el concepto de "mensaje que no come nada". Gracias –

+0

¿Y ahora qué? Deben usar algún tipo de equivalente __set() y __get() para que su marco de estilo RPC funcione realmente. No puedo decir cómo funciona desde el código fuente. – BMiner

1

Si está buscando algo así como la función __get() de PHP, no creo que Javascript proporcione ninguna construcción de este tipo.

Lo mejor que se me ocurre hacer es recorrer los miembros no funcionales del objeto y luego crear una función correspondiente "getXYZ()" para cada uno.

En el código pseudo-ish poco fiables:

for (o in this) { 
    if (this.hasOwnProperty(o)) { 
     this['get_' + o] = function() { 
      // return this.o -- but you'll need to create a closure to 
      // keep the correct reference to "o" 
     }; 
    } 
} 
5

Javascript 1.5 sí tiene getter/settersyntactic sugar. John Resig lo explicó muy bien here

No es lo suficientemente genérico para uso web, pero ciertamente Firefox lo tiene (también Rhino, si alguna vez quieres usarlo en el lado del servidor).

+5

No del todo __get() y __set(). La versión de PHP le permite monitorear TODAS las propiedades, incluso aquellas que aún no se han creado. – BMiner

5

Si realmente necesita una aplicación que funciona, se puede "engañar" a su manera arround probando el segundo parámetro contra undefined, esto también significa que usted podría utilizar para obtener el parámetro de comienzo ajustada.

var foo = { 
    args: {}, 

    __noSuchMethod__ : function(id, args) { 
     if(args === undefined) { 
      return this.args[id] === undefined ? this[id] : this.args[id] 
     } 

     if(this[id] === undefined) { 
      this.args[id] = args; 
     } else { 
      this[id] = args; 
     } 
    } 
}; 
1

Terminé usando la respuesta de un pífano para construir mi propia solución. Mi solución creará automáticamente las funciones get_ {propname} y set_ {propname} para todas las propiedades. Verifica si la función ya existe antes de agregarlos. Esto le permite anular el método de obtención o configuración predeterminado con nuestra propia implementación sin el riesgo de sobrescribirlo.

for (o in this) { 
     if (this.hasOwnProperty(o)) { 
      var creategetter = (typeof this['get_' + o] !== 'function'); 
      var createsetter = (typeof this['set_' + o] !== 'function'); 
      (function() { 
       var propname = o; 
       if (creategetter) { 
        self['get_' + propname] = function() { 
         return self[propname]; 
        }; 
       } 
       if (createsetter) { 
        self['set_' + propname] = function (val) { 
         self[propname] = val; 
        }; 
       } 
      })(); 
     } 
    } 
32

Proxy ¡Hazlo! ¡Estoy tan feliz de que esto exista! Aquí se da una respuesta: Is there a javascript equivalent of python's __getattr__ method?. Para reformular en mis propias palabras:

var x = new Proxy({},{get(target,name) { 
    return "Its hilarious you think I have "+name 
}}) 

console.log(x.hair) // logs: "Its hilarious you think I have hair" 

Proxy para la victoria! Consulte los documentos de MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Funciona en chrome, firefox y node.js. Desventajas: no funciona en IE - freakin IE. Pronto.

+0

Funciona también en Edge. Ver [caniuse.com] (https://caniuse.com/#feat=proxy) para versiones específicas del navegador. – styfle

13

Si está codificando en ES6 puede combinar proxy y clase para tener un buen código el aspecto de php:

class Magic { 
    constructor() { 
     return new Proxy(this, this); 
    } 
    get (target, prop) { 
     return this[prop] || 'MAGIC'; 
    } 
} 

este se une al controlador, para que pueda utilizar este lugar de destino.

Nota: a diferencia de PHP, el proxy maneja todas las solicitudes de propiedad.

let magic = new Magic(); 
magic.foo = 'NOT MAGIC'; 
console.log(magic.foo); // NOT MAGIC 
console.log(magic.bar); // MAGIC 

Puede comprobar qué navegadores soporte de proxy http://caniuse.com/#feat=proxy y la clase http://caniuse.com/#feat=es6-class. El nodo 8 admite ambos.

+0

Esta es la mejor respuesta que he encontrado. –

+0

^esto es genio – Ifnot

Cuestiones relacionadas