Cập nhật 2013 và 2015 (xem bên dưới để biết câu trả lời gốc từ năm 2011) :
Điều này đã thay đổi kể từ thông số ES2015 (còn gọi là "ES6"): JavaScript hiện có proxy . Proxy cho phép bạn tạo các đối tượng là proxy thực sự cho (các mặt trên) các đối tượng khác. Đây là một ví dụ đơn giản biến mọi giá trị thuộc tính là chuỗi thành tất cả các giới hạn khi truy xuất:
"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"
Các hoạt động bạn không ghi đè có hành vi mặc định của họ. Ở trên, tất cả chúng ta ghi đè là get
, nhưng có toàn bộ danh sách các thao tác bạn có thể nối vào.
Trong get
danh sách đối số của hàm xử lý:
target
là đối tượng được ủy nhiệm ( original
, trong trường hợp của chúng tôi).
name
là (tất nhiên) tên của tài sản đang được lấy, thường là một chuỗi nhưng cũng có thể là một Biểu tượng.
receiver
là đối tượng nên được sử dụng như this
trong hàm getter nếu thuộc tính là một trình truy cập chứ không phải là một thuộc tính dữ liệu. Trong trường hợp bình thường, đây là proxy hoặc thứ gì đó thừa hưởng từ nó, nhưng nó có thể là bất cứ thứ gì vì bẫy có thể được kích hoạt bởi Reflect.get
.
Điều này cho phép bạn tạo một đối tượng với tính năng getter và setter bắt tất cả bạn muốn:
"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}`);
Đầu ra của ở trên là:
Nhận tài sản không tồn tại 'foo'
[trước] obj.foo = không xác định
Đặt thuộc tính không tồn tại 'foo', giá trị ban đầu: bar
[sau] obj.foo = thanh
Lưu ý cách chúng tôi nhận được thông báo "không tồn tại" khi chúng tôi cố gắng truy xuất foo
khi nó chưa tồn tại và một lần nữa khi chúng tôi tạo nó, nhưng không phải sau đó.
Trả lời từ năm 2011 (xem phần cập nhật 2013 và 2015) :
Không, JavaScript không có tính năng thuộc tính bắt tất cả. Cú pháp của trình truy cập mà bạn đang sử dụng được trình bày trong Phần 11.1.5 của thông số kỹ thuật và không cung cấp bất kỳ ký tự đại diện nào hoặc đại loại như thế.
Tất nhiên, bạn có thể thực hiện một chức năng để làm điều đó, nhưng tôi đoán có lẽ bạn không muốn sử dụng f = obj.prop("foo");
hơn là f = obj.foo;
và obj.prop("foo", value);
hơn là obj.foo = value;
(điều này cần thiết cho chức năng để xử lý các thuộc tính không xác định).
FWIW, hàm getter (tôi không bận tâm với logic setter) sẽ trông giống như thế này:
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...
};
Nhưng một lần nữa, tôi không thể tưởng tượng bạn thực sự muốn làm điều đó, vì cách nó thay đổi cách bạn sử dụng đối tượng.