2010-02-26 14 views
9

Estoy buscando una forma de manejar llamadas a métodos y propiedades indefinidos en JavaScript.¿Hay algún método que pueda sobrecargar para manejar propiedades indefinidas en JavaScript?

Estos serían similares a los métodos mágicos PHP __call, __callStatic, __get.

Un ejemplo del código que utiliza este podría ser:

var myObject = {}; 
myObject.__call = function (called, args) { 
    alert(called); 
    alert(args); 
    return(true); 
} 

myObject.meow("kitty", "miau"); 

Esto resultaría en el primer diálogo de alerta que muestra "maullido" y el segundo para mostrar "gatito, miau".

Respuesta

-1

Hay una función mágica en Javascript llamada __noSuchMethod__. Aquí está un ejemplo:

var foo = { __noSuchMethod__ : function(name,params) { alert('invalid function call'); } } 
foo.bar(); 

EDIT: Como @jldupont mencionado, esto es en realidad sólo en Rhino y SpiderMonkey (motor de JS de Mozilla); no es compatible con el estándar ECMAScript. Hay algunas solicitudes que esté en ECMAScript 4.

+3

esto no es estándar ... – jldupont

+0

ni siquiera en V8: http://code.google.com/p/v8/issues/detail?id=264 – jldupont

+0

OP nunca lo mencionó como un requisito; por lo que sé, podría estar usando Rhino. solo diciendo, esta es una forma de hacerlo. –

-1

debo añadir para que la gente todavía en busca de una solución, no es lo siguiente:

var myObject = {}; 
myObject['dynamicMethod'] = new function (parameters) { 
    alert(parameters); 
}; 

La única diferencia aquí es que puede que tenga que recorrer más de lo tienes la intención de agregar Esto es pregenerar los métodos, en lugar de simplemente manejarlos dinámicamente.

0

Si solo quieres algo como las características de PHP, lee la siguiente solución que se me ocurrió. Supongo que pondrás esta funcionalidad en tus propios objetos. Bueno, mientras no sean funciones, puede tener la siguiente convención por conveniencia, y debería funcionar en todos los navegadores:

en lugar de myobj.foo o myobj ['foo'], simplemente use myobj (' foo '), y hacer que tu objeto se llame cuando lo defines. Pero deberá evitar el uso de "nuevo" porque "nuevo" nunca puede devolver una función en Javascript.

var NewFlexible = function() { 
    var custom = {}; 
    return function(prop) { 
    if (!(prop in custom)) custom.prop = null; 
    return custom.prop; 
    }; 
}; 

Y a continuación, puede crear objetos de esta manera:

myObj = NewFlexible(); 

el uso de algo similar al patrón de Douglas Crockford, puede crear "clases" que se extienden a lo siguiente:

var NewDerived = function(options) { 
    var result = {}; 
    NewFlexible.apply(result, arguments); // parent constructor 
    // go on to do what you have to do 
    return result; 
}; 

O , para olvidarse de los constructores, puede hacer un contenedor alrededor de los objetos:

var MakeFlexible = function (obj) { 
return function(prop) { 
    if ('prop' in obj) return obj.prop; 
    obj.prop = null; return obj.prop; 
}; 
} 

Simplemente tendrá que publicar esta documentación para todos los usuarios de su código. En realidad, es bueno exponer tu funcionalidad a través de esta convención porque no quieres asustar a la gente mediante el uso de JavaScript no estándar.

+0

Pero este * es * básicamente Javascript no estándar. Esto está bien para proyectos rápidos, pero no recomendaría comenzar una gran base de código usando este patrón. –

+0

Solo estoy tratando de ser útil. Claramente parecía que el tipo quería una funcionalidad similar a PHP por alguna razón, es decir, una notación conveniente para acceder a las propiedades que no estaban allí. Así que la cosa más fácil de lo que podía pensar es tener objetos que apoyan foo ('bar') en lugar de foo [ 'bar'], que es bastante cercano a lo que el tipo quería, sin necesidad de utilizar las propiedades de JavaScript no estándar. Esto está usando Javascript bastante estándar. Funcionará en todos los navegadores. El hecho de que podría ser un deseo inusual no es mi culpa, es lo más cercano que puede obtener (en mi humilde opinión) para responder la pregunta mientras usa el JS correcto. – Magarshak

-1

Si está buscando específicamente un método, tendrá que esperar hasta ES7, porque parece que no lo van a incluir de esa manera en armonía, de todos modos, hay una funcionalidad estándar de trabajo actualmente en esto, a través del Proxy de objeto incorporado, que se agrega en ES6, escribí una respuesta, en this question, que toma el problema de una manera más amplia. implica Básicamente envolver el objeto en un proxy, una carga de un controlador de

get: function(obj, propname) {custom handling} 

en el constructor Está proxy de trought, de manejar, filtro o implementar todas las solicitudes de de propiedades en ella.

Y añade aún más funcionalidad .... Para la respuesta completa, entra en el enlace.

+0

Proxy está en ES6? –

4

Proxy puede hacerlo! Proxy puede hacer TODO! Aquí se da una respuesta: Is there a javascript equivalent of python's __getattr__ method?. Para reformular en mis propias palabras:

var myObject = new Proxy({},{get(target,name) { 
    return function() { 
    alert(name) 
    console.log(arguments) // alerts are bleh 
    return true 
    } 
}}) 

myObject.meow("kitty", "miau") // alerts "meow", logs ["kitty","miau"] to the console, and returns true 

Mira la documentación MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Obras en Chrome, Firefox, y Node.js. Desventajas: no funciona en IE - freakin IE. Pronto.

+1

Esta debe ser la respuesta aceptada - es estándar y ahora muy bien soportado: https://caniuse.com/#search=Proxy –

+0

Aún no soportados por el IE aunque al parecer. –

+0

Afortunadamente hay una polyfill de la trampa llegar: https://github.com/GoogleChrome/proxy-polyfill –

Cuestiones relacionadas