Оновлення 2013 та 2015 років (див. Нижче оригінальну відповідь від 2011 року) :
Це змінилося станом із специфікації ES2015 (він же "ES6"): у JavaScript зараз є проксі . Проксі-сервери дозволяють створювати об’єкти, які є справжніми проксі-серверами для (фасадів) інших об'єктів. Ось простий приклад, який перетворює будь-які значення властивостей, які є рядками для всіх обмежень під час пошуку:
"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"
Операції, які ви не перекриваєте, мають свою поведінку за замовчуванням. У вищесказаному все, що ми перекриваємо, є get
, але є цілий список операцій, до яких можна підключитись.
У get
списку аргументів функції обробника:
target
є об'єктом проксі ( original
у нашому випадку).
name
це (звичайно) назва отриманого властивості, яке зазвичай є рядком, але також може бути символом.
receiver
- це об'єкт, який слід використовувати як this
у функції getter, якщо властивість є аксесуаром, а не властивістю даних. У звичайному випадку це проксі-сервер або щось, що від нього успадковується, але це може бути будь-що, оскільки можливе спрацювання пастки Reflect.get
.
Це дозволяє вам створити об'єкт за допомогою потрібної функції прибирання та налаштування:
"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}`);
Вихід із зазначеного вище:
Отримання неіснуючої власності "foo"
[раніше] obj.foo = невизначений
Встановлення неіснуючого властивості 'foo', початкове значення: bar
[після] obj.foo = бар
Зверніть увагу, як ми отримуємо "неіснуюче" повідомлення, коли ми намагаємося отримати foo
його, коли воно ще не існує, і знову, коли ми створюємо його, але не після цього.
Відповідь від 2011 року (див. Вище для оновлень 2013 та 2015 років) :
Ні, у JavaScript немає властивості загального використання. Синтаксис аксесуара, який ви використовуєте, міститься в розділі 11.1.5 специфікації, і він не пропонує жодної підстановки чи чогось подібного.
Можна, звичайно, реалізувати функцію , щоб зробити це, але я припускаю , що ви , ймовірно , не хочете використовувати f = obj.prop("foo");
замість f = obj.foo;
і obj.prop("foo", value);
замість того , obj.foo = value;
(що було б необхідно для функції для обробки невідомих властивостей).
FWIW, функція геттера (я не переймався логікою сеттера) виглядала б приблизно так:
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...
};
Але знову ж таки, я не можу уявити, що ви дійсно хочете це зробити через те, як це змінюється як ви використовуєте об'єкт.