Atualização de 2013 e 2015 (veja abaixo a resposta original de 2011) :
Isso foi alterado conforme a especificação do ES2015 (também conhecida como "ES6"): o JavaScript agora possui proxies . Os proxies permitem criar objetos que são proxies verdadeiros para (fachadas) outros objetos. Aqui está um exemplo simples que transforma todos os valores de propriedade que são cadeias de caracteres em todos os limites na recuperação:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let original = {
"foo": "bar"
};
let proxy = new Proxy(original, {
get(target, name, receiver) {
let rv = Reflect.get(target, name, receiver);
if (typeof rv === "string") {
rv = rv.toUpperCase();
}
return rv;
}
});
console.log(`original.foo = ${original.foo}`); // "original.foo = bar"
console.log(`proxy.foo = ${proxy.foo}`); // "proxy.foo = BAR"
As operações que você não substitui têm seu comportamento padrão. Acima, tudo o que substituímos é get
, mas há uma lista completa de operações nas quais você pode se conectar.
Na get
lista de argumentos da função de manipulador:
target
é o objeto que está sendo procurado ( original
, no nosso caso).
name
é (é claro) o nome da propriedade que está sendo recuperada, que geralmente é uma string, mas também pode ser um símbolo.
receiver
é o objeto que deve ser usado como this
na função getter se a propriedade for um acessador e não uma propriedade de dados. No caso normal, esse é o proxy ou algo que herda dele, mas pode ser qualquer coisa, já que a armadilha pode ser acionada Reflect.get
.
Isso permite que você crie um objeto com o recurso catch-all getter e setter que você deseja:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let obj = new Proxy({}, {
get(target, name, receiver) {
if (!Reflect.has(target, name)) {
console.log("Getting non-existent property '" + name + "'");
return undefined;
}
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
if (!Reflect.has(target, name)) {
console.log(`Setting non-existent property '${name}', initial value: ${value}`);
}
return Reflect.set(target, name, value, receiver);
}
});
console.log(`[before] obj.foo = ${obj.foo}`);
obj.foo = "bar";
console.log(`[after] obj.foo = ${obj.foo}`);
A saída do acima é:
Obtendo a propriedade inexistente 'foo'
[antes] obj.foo = indefinido
Configurando a propriedade inexistente 'foo', valor inicial: bar
[depois] obj.foo = bar
Observe como recebemos a mensagem "inexistente" quando tentamos recuperar foo
quando ela ainda não existe, e novamente quando a criamos, mas não depois disso.
Resposta de 2011 (veja acima para atualizações de 2013 e 2015) :
Não, o JavaScript não possui um recurso de propriedade abrangente. A sintaxe do acessador que você está usando é abordada na Seção 11.1.5 da especificação e não oferece nenhum curinga ou algo parecido.
Você poderia, é claro, implementar uma função para fazê-lo, mas acho que você provavelmente não deseja usar em f = obj.prop("foo");
vez de f = obj.foo;
e em obj.prop("foo", value);
vez de obj.foo = value;
(o que seria necessário para a função manipular propriedades desconhecidas).
FWIW, a função getter (eu não me incomodei com a lógica do setter) ficaria assim:
MyObject.prototype.prop = function(propName) {
if (propName in this) {
// This object or its prototype already has this property,
// return the existing value.
return this[propName];
}
// ...Catch-all, deal with undefined property here...
};
Mas, novamente, não consigo imaginar que você realmente queira fazer isso, por causa de como isso muda a maneira como você usa o objeto.