CẬP NHẬT 2015:
Như đã chỉ ra trong câu trả lời của 7th , bây giờ ES6 (ECMAScript 2015) đã được hoàn thiện, tài liệu thích hợp hơn hiện đã có:
Câu trả lời gốc (để hiểu (lịch sử) và các ví dụ bổ sung) :
Các Reflection proposal
dường như đã tiến triển đến Dự thảo ECMAScript 6 Đặc điểm kỹ thuật . Tài liệu này hiện phác thảo các Reflect
phương thức của -object và chỉ nêu những điều sau về Reflect
-object chính nó:
Đối tượng Reflect là một đối tượng bình thường duy nhất.
Giá trị của khe bên trong [[Prototype]] của đối tượng Reflect là đối tượng nguyên mẫu Object được tích hợp sẵn tiêu chuẩn (19.1.3).
Đối tượng Reflect không phải là một đối tượng chức năng. Nó không có phương thức bên trong [[Construct]]; không thể sử dụng đối tượng Reflect làm hàm tạo với toán tử mới . Đối tượng Reflect cũng không có phương thức bên trong [[Gọi]]; không thể gọi đối tượng Reflect dưới dạng một hàm.
Tuy nhiên, có một lời giải thích ngắn gọn về mục đích của nó trong ES Harmony :
Mô-đun “@reflect” phục vụ nhiều mục đích:
- Bây giờ chúng ta đã có các mô-đun, mô-đun “@reflect” là một nơi tự nhiên hơn cho nhiều phương thức phản chiếu được định nghĩa trước đó trên Đối tượng. Đối với mục đích tương thích ngược, không có khả năng các phương thức tĩnh trên Đối tượng sẽ biến mất. Tuy nhiên, các phương thức mới có thể sẽ được thêm vào mô-đun “@reflect” hơn là vào phương thức khởi tạo Đối tượng.
- Ngôi nhà tự nhiên dành cho proxy, tránh sự cần thiết phải ràng buộc Proxy toàn cầu.
- Hầu hết các phương pháp trong mô-đun này ánh xạ 1-1 vào các bẫy Proxy. Trình xử lý proxy cần các phương pháp này để chuyển tiếp các thao tác một cách thuận tiện, như được hiển thị bên dưới.
Vì vậy, Reflect
đối tượng cung cấp một số hàm tiện ích, nhiều hàm có vẻ trùng lặp với các phương thức ES5 được định nghĩa trên Đối tượng toàn cục.
Tuy nhiên, điều đó không thực sự giải thích những vấn đề hiện có mà điều này dự định giải quyết hoặc chức năng nào được thêm vào. Tôi nghi ngờ điều này có thể được lung linh và thực sự, sự hài hòa-đặc điểm kỹ thuật ở trên liên kết với một 'triển khai gần đúng, không quy chuẩn của các phương pháp này' .
Việc kiểm tra mã đó có thể cung cấp (thêm) ý tưởng về việc sử dụng nó, nhưng may mắn thay, cũng có một wiki nêu ra một số lý do tại sao đối tượng Reflect lại hữu ích :
(Tôi đã sao chép (và định dạng) văn bản sau để tham khảo trong tương lai từ đó nguồn vì chúng là những ví dụ duy nhất mà tôi có thể tìm thấy. Ngoài ra, chúng có ý nghĩa, đã có lời giải thích tốt và chạm vào apply
ví dụ của câu hỏi .)
Giá trị trả lại hữu ích hơn
Nhiều hoạt động trong Reflect
tương tự như các hoạt động ES5 được định nghĩa trên Object
, chẳng hạn như Reflect.getOwnPropertyDescriptor
và Reflect.defineProperty
. Tuy nhiên, ngược lại Object.defineProperty(obj, name, desc)
sẽ trả về obj
khi thuộc tính được xác định thành công, hoặc ném ra một TypeError
cách khác, Reflect.defineProperty(obj, name, desc)
được chỉ định đơn giản là trả về một boolean cho biết thuộc tính có được xác định thành công hay không. Điều này cho phép bạn cấu trúc lại mã này:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
Về điều này:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
Các phương thức khác trả về trạng thái thành công boolean như vậy là Reflect.set
(để cập nhật một thuộc tính), Reflect.deleteProperty
(để xóa một thuộc tính), Reflect.preventExtensions
(để làm cho một đối tượng không thể mở rộng được) và Reflect.setPrototypeOf
(để cập nhật liên kết nguyên mẫu của một đối tượng).
Hoạt động hạng nhất
Trong ES5, cách để phát hiện một đối tượng có obj
định nghĩa hay kế thừa một tên thuộc tính nhất định hay không là viết (name in obj)
. Tương tự, để xóa một thuộc tính, người ta sử dụng delete obj[name]
. Mặc dù cú pháp dành riêng rất hay và ngắn gọn, nhưng điều đó cũng có nghĩa là bạn phải gói rõ ràng các hoạt động này trong các hàm khi bạn muốn chuyển hoạt động xung quanh dưới dạng giá trị hạng nhất.
Với Reflect
, các phép toán này dễ dàng được định nghĩa là các hàm hạng nhất:
Reflect.has(obj, name)
là hàm tương đương với (name in obj)
và Reflect.deleteProperty(obj, name)
là một hàm hoạt động giống nhưdelete obj[name].
Ứng dụng chức năng đáng tin cậy hơn
Trong ES5, khi người ta muốn gọi một hàm f
với một số lượng biến đối số được đóng gói dưới dạng một mảng args
và liên kết this
giá trị với obj
, người ta có thể viết:
f.apply(obj, args)
Tuy nhiên, f
có thể là một đối tượng cố ý hoặc vô ý xác định apply
phương thức riêng của nó . Khi bạn thực sự muốn đảm bảo rằng apply
hàm tích hợp được gọi, người ta thường viết:
Function.prototype.apply.call(f, obj, args)
Không chỉ dài dòng, nó nhanh chóng trở nên khó hiểu. Với Reflect
, giờ đây bạn có thể thực hiện một lệnh gọi hàm đáng tin cậy theo cách ngắn gọn và dễ hiểu hơn:
Reflect.apply(f, obj, args)
Các hàm tạo đối số biến
Hãy tưởng tượng bạn muốn gọi một hàm khởi tạo với một số đối số thay đổi. Trong ES6, nhờ cú pháp lây lan mới, có thể viết mã như:
var obj = new F(...args)
Trong ES5, điều này khó viết hơn, bởi vì người ta chỉ có thể sử dụng F.apply
hoặc F.call
gọi một hàm với số lượng đối số thay đổi, nhưng không có F.construct
hàm nào đối new
với hàm có số đối số thay đổi. Với Reflect
, bây giờ người ta có thể viết, trong ES5:
var obj = Reflect.construct(F, args)
Hành vi chuyển tiếp mặc định cho bẫy Proxy
Khi sử dụng Proxy
các đối tượng để bọc các đối tượng hiện có, việc chặn một thao tác, thực hiện một cái gì đó và sau đó là "làm điều mặc định", thường là áp dụng thao tác bị chặn cho đối tượng được bọc. Ví dụ: giả sử tôi chỉ muốn ghi lại tất cả các quyền truy cập thuộc tính vào một đối tượng obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Các Reflect
và Proxy
API được thiết kế song song , chẳng hạn rằng đối với mỗi Proxy
cái bẫy, có tồn tại một phương pháp tương ứng trên Reflect
rằng "làm điều mặc định". Do đó, bất cứ khi nào bạn thấy mình muốn "làm điều mặc định" bên trong trình xử lý Proxy, điều chính xác cần làm là luôn gọi phương thức tương ứng trong Reflect
đối tượng:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
Kiểu trả về của các Reflect
phương thức được đảm bảo tương thích với kiểu trả về của Proxy
bẫy.
Kiểm soát ràng buộc này của những người truy cập
Trong ES5, khá dễ dàng để thực hiện truy cập thuộc tính chung hoặc cập nhật thuộc tính. Ví dụ:
var name = ...
obj[name]
obj[name] = value
Các Reflect.get
và Reflect.set
phương thức cho phép bạn làm điều tương tự, nhưng cũng chấp nhận như một đối số tùy chọn cuối cùng, một receiver
tham số cho phép bạn đặt this
-binding một cách rõ ràng khi thuộc tính mà bạn lấy / đặt là một trình truy cập:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
Điều này đôi khi hữu ích khi bạn đang gói obj
và bạn muốn mọi tự gửi trong trình truy cập được định tuyến lại đến trình bao bọc của bạn, ví dụ: nếu obj
được định nghĩa là:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Cuộc gọi Reflect.get(obj, "foo", wrapper)
sẽ khiến this.bar()
cuộc gọi được định tuyến lại wrapper
.
Tránh di sản __proto__
Trên một số trình duyệt, __proto__
được định nghĩa là một thuộc tính đặc biệt cho phép truy cập vào nguyên mẫu của một đối tượng. ES5 đã chuẩn hóa một phương pháp mới Object.getPrototypeOf(obj)
để truy vấn nguyên mẫu. Reflect.getPrototypeOf(obj)
làm chính xác như vậy, ngoại trừ điều đó Reflect
cũng xác định một tương ứng Reflect.setPrototypeOf(obj, newProto)
để thiết lập nguyên mẫu của đối tượng. Đây là cách mới tuân thủ ES6 để cập nhật nguyên mẫu của đối tượng.
Lưu ý rằng: setPrototypeOf
cũng tồn tại trênObject
(như được chỉ một cách chính xác hiện bởi KNU 's bình luận )!
CHỈNH SỬA:
Ghi chú bên lề (giải quyết các nhận xét cho câu hỏi Q): Có một câu trả lời ngắn gọn và đơn giản về 'Q: Mô-đun ES6 so với Nhập khẩu HTML' giải thích Realms
và Loader
đối tượng.
Một lời giải thích khác được cung cấp bởi liên kết này :
Một đối tượng cảnh giới trừu tượng hóa khái niệm về một môi trường toàn cầu riêng biệt, với đối tượng toàn cục của riêng nó, bản sao của thư viện chuẩn và "bản chất" (các đối tượng chuẩn không bị ràng buộc với các biến toàn cục, như giá trị ban đầu của Object.prototype).
Web có thể mở rộng : Đây là tương đương động của cùng một nguồn gốc
<iframe>
không có DOM.
Đáng nói hơn là: tất cả điều này vẫn còn trong bản nháp, đây không phải là một thông số kỹ thuật được khắc trên đá! Đó là ES6, vì vậy hãy ghi nhớ khả năng tương thích của trình duyệt!
Hi vọng điêu nay co ich!
Reflect
chỉ là một vật chứaRealm
vàLoader
các đối tượng, nhưng tôi cũng không biết cái sau làm gì.