JavaScript getter para todas as propriedades
-
13-09-2019 - |
Pergunta
Para encurtar a história:. Eu estou em uma situação onde eu gostaria de um getter-style PHP, mas em JavaScript
O meu JavaScript é executado no Firefox somente, assim Mozilla específica JS é OK por mim.
A única maneira que eu posso encontrar para fazer um getter JS requer especificando o seu nome, mas eu gostaria de definir um getter para todas nomes possíveis. Eu não tenho certeza se isso é possível, mas eu gostaria muito de saber.
Solução
Proxy
pode fazê-lo! Estou tão feliz isso existe !! Uma resposta é dada aqui: Existe uma javascript equivalente a __getattr__ de python método? . Para reformular em minhas próprias palavras:
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 a vitória! Confira o MDN docs: https: //developer.mozilla .org / pt-bR / docs / web / JavaScript / Referência / Global_Objects / Proxy
Obras em Chrome, Firefox, e Node.js. Desvantagens: não funciona no IE - maldito IE. Em breve.
Outras dicas
O mais próximo que você pode encontrar é __noSuchMethod__ , que é de JavaScript equivalente a __call () do PHP.
Infelizmente, não há equivalente a __get / __ set, que é uma vergonha, porque com eles, poderíamos ter implementado __noSuchMethod__, mas eu ainda não vejo uma maneira de implementar propriedades (como em C #) usando __noSuchMethod __.
var foo = {
__noSuchMethod__ : function(id, args) {
alert(id);
alert(args);
}
};
foo.bar(1, 2);
Se você está codificando em ES6 você pode combinar proxy e classe para ter um boa aparência código como php :
class Magic {
constructor () {
return new Proxy(this, this);
}
get (target, prop) {
return this[prop] || 'MAGIC';
}
}
Isso vincula para o manipulador, assim você pode usar isso em vez de alvo.
Nota:. Ao contrário de PHP, alças de proxy todo o pedido Propriedade
let magic = new Magic();
magic.foo = 'NOT MAGIC';
console.log(magic.foo); // NOT MAGIC
console.log(magic.bar); // MAGIC
Você pode verificar quais navegadores de proxy apoio http://caniuse.com/#feat=proxy e classe http://caniuse.com/#feat=es6-class . Nó 8 suporte ambos.
Javascript 1,5 tem getter / setter sintática açúcar. É muito bem explicado por John Resig aqui
Não é suficiente genérico para uso da web, mas certamente Firefox tem deles (também Rhino, se você quiser usá-lo no lado do servidor).
Se você realmente precisa de uma implementação que funciona, você poderia "enganar" o seu caminho espalhados testando o segundo parâmetro contra undefined
, isso também significa que você poderia usar chegar ao parâmetro realmente set.
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;
}
}
};
Se você está procurando algo como do PHP __get()
função, eu não acho que o Javascript fornece qualquer construção.
O melhor que posso pensar em fazer é looping através de membros não-função do objeto e, em seguida, a criação de um "getXYZ ()" correspondente função para cada um.
No código pseudo-ish desonesto:
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"
};
}
}
Acabei usando responder a uma nickfs para construir a minha própria solução. Minha solução criará automaticamente get_ {propname} e {set_ PROPNAME} funções para todas as propriedades. Ele verifique se a função já existe antes de adicioná-los. Isso permite que você substituir o get padrão ou método conjunto com a nossa própria implementação sem o risco de ele ficar substituído.
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;
};
}
})();
}
}