2011-08-08 35 views
24

Làm cách nào để mô phỏng các trình gỡ rối/định dạng __get() và __set() trong JavaScript? Rất nhiều người nói rằng điều này hiện tại là không thể. Tôi gần như chắc chắn rằng nó có thể bởi vì các dự án như nowjs (http://nowjs.com) làm một cái gì đó như thế này.Giám sát tất cả các thuộc tính đối tượng JavaScript (getters và setters ma thuật)

Tôi biết rằng bạn có thể sử dụng getset, nhưng những điều này không hoạt động khi bạn không chắc chắn tên thuộc tính sẽ là gì. Ví dụ: nếu bạn muốn trình xử lý sự kiện thực thi khi thuộc tính mới được tạo thì sao?

Ví dụ về những gì tôi muốn làm:

var obj = {}; 
notify(obj, function(key, value) { 
    //key is now the name of the property being set. 
    //value is the value of the property about to be set 
    console.log("setting " + key + " to " + value); 
}); 
obj.foo = 2; //prints "setting foo to 2" 
obj.bar = {a: 2}; //prints "setting bar to [Object]" 
//Notice that notify() worked even though 'foo' and 'bar' weren't even defined yet! 

(Câu hỏi đặt ra là tương tự như các câu hỏi sau:

)

EDIT: Dường như tính năng này được gọi là "proxy động" và sẽ xuất hiện trong tiêu chuẩn "Harmony" ECMAScript (có thể là ES6). Bạn có thể đọc thêm here. Một đối tượng 'Proxy' mới được giới thiệu với một vài phương thức (I.e. Create() và createFunction()).

Người ta có thể làm điều này:

//Constructing an object proxy (proto is optional) 
var proxy = Proxy.create(handler, proto); 
proxy.foo = 2; //Triggers 'set' function in the handler (read about it) 

Bottom line ở đây: nó không hoạt động trong hầu hết các trình duyệt, nhưng một thực hiện có sẵn cho Node.js: node-proxy.

+1

Tính năng này được gọi là proxy là một phần của ECMAScript 6 không 5. – Raynos

+0

Bắt tốt. Đã sửa đổi bài đăng của tôi. Cảm ơn! – BMiner

Trả lời

12

Nhìn qua mã nguồn ngay bây giờ, tôi tin rằng họ làm điều này bằng cách liên tục theo dõi đối tượng now và đẩy các thay đổi giữa máy khách và máy chủ bất cứ khi nào chúng được phát hiện. Tôi thừa nhận tôi đã không hoàn toàn grokked mã của họ được nêu ra, tuy nhiên.

Trong trình duyệt, thao tác này sẽ được thực hiện với một số lỗ hổng vui nhộn setInterval.

EDIT: vâng, đó thực sự là những gì họ làm: line 368 của khách hàng now.js. Họ làm some more tricks để một khi một thuộc tính mới được phát hiện, việc truy cập trong tương lai đối với nó được bắt giữ bởi getters và setters, nhưng những sửa đổi đó chỉ được thực hiện mỗi 1000 ms trong một setTimeout.

Một bằng chứng khác cho thấy điều này là không thể trong JavaScript hiện tại là the proxies proposal for ECMAScript Harmony được thiết kế rõ ràng để cho phép các tình huống như vậy, ngụ ý rất mạnh mẽ rằng chúng không thể thực hiện được. Các trình duyệt Mozilla gần đây có a prototype proxies implementation, nếu có lẽ là đủ. Và rõ ràng là V8 is working to add support, điều này có thể đủ tùy thuộc vào phiên bản nào của Nút V8 đang sử dụng những ngày này.

EDIT2: oh mát mẻ, trên máy chủ bên rõ ràng nowjs không sử dụng proxy! Điều này có nghĩa là chúng đủ trưởng thành trong Node để bạn sử dụng. Xem những gì họ làm tại https://github.com/Flotype/now/blob/master/lib/proxy.js. Hoặc chỉ cần thực hiện var Proxy = require("nodejs-proxy") và hy vọng họ tuân thủ thông số để bạn có thể tận dụng tài liệu từ MDC và các nơi khác.

+0

Được rồi ... Tôi có thể hiểu các lỗ hổng phía máy khách, đặc biệt là b/c các vấn đề tương thích với trình duyệt. Điều gì về phía máy chủ? Giống như, trên Node.JS? Bạn có nghĩ rằng có thể làm điều gì đó ở đó không? – BMiner

+2

Tôi thực sự chỉ chỉnh sửa bài đăng của tôi với những phát hiện của tôi ở đó khi bạn đang bình luận :) – Domenic

0

Có lẽ this post sẽ giúp ...? Đó là tuy nhiên, chỉ cho các thuộc tính cụ thể và các trình duyệt dựa trên Gecko ... Nếu bạn cần hỗ trợ cho các trình duyệt khác, lỗi của nó, nhưng bạn có thể xem xét onpropertychange. Đây là số MSDN Page. Hy vọng rằng sẽ giúp một chút ...

+0

Cảm ơn sự giúp đỡ của bạn. onpropertychange trông giống như nó chỉ dành cho đối tượng DOM. Điều này sẽ cần phải làm việc cho các đối tượng JS nguyên đơn giản. – BMiner

2

Trong Firefox, bạn có thể sử dụng Object.watch. Nếu bạn xem chủ đề này, Object.watch() for all browsers?, có một ví dụ về việc sử dụng nó giống như trong tất cả các trình duyệt.

Rất tiếc, tôi vừa mới nhận ra rằng bạn muốn xem tất cả các thuộc tính chứ không phải thuộc tính cụ thể ... Giải pháp trên là để xem một thuộc tính cụ thể.

Các vấn đề liên quan