2016-03-28 23 views
28

Có cách tiếp cận khác không?Tại sao Object.observe() không được chấp nhận

Có cách nào khác để thực hiện phát hiện thay đổi trong đối tượng không?

Có phương pháp Proxy, nhưng bất cứ ai có thể cho tôi biết làm thế nào tôi có thể đạt được điều này sử dụng Proxy:

var obj = { 
    foo: 0, 
    bar: 1 
}; 

Object.observe(obj, function(changes) { 
    console.log(changes); 
}); 

obj.baz = 2; 
// [{name: 'baz', object: <obj>, type: 'add'}] 

obj.foo = 'hello'; 
// [{name: 'foo', object: <obj>, type: 'update', oldValue: 0}] 
+2

'Proxy()' hiện có ngay bây giờ! – Jai

+1

[Proxy] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy) –

+1

Hoặc sử dụng [getter] (https://developer.mozilla.org/en/docs/ Web/JavaScript/Tham chiếu/Hàm/get) hoặc [setter] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/set) –

Trả lời

34

Bạn có thể đạt được điều này với getter và setter.

var obj = { 
    get foo() { 
    console.log({ name: 'foo', object: obj, type: 'get' }); 
    return obj._foo; 
    }, 
    set bar(val) { 
    console.log({ name: 'bar', object: obj, type: 'set', oldValue: obj._bar }); 
    return obj._bar = val; 
    } 
}; 

obj.bar = 2; 
// {name: 'baz', object: <obj>, type: 'set', oldValue: undefined} 

obj.foo; 
// {name: 'foo', object: <obj>, type: 'get'} 

Hoặc, trong trình duyệt có hỗ trợ dành cho Proxy, bạn có thể viết giải pháp chung chung hơn.

var obj = { 
    foo: 1, 
    bar: 2 
}; 

var proxied = new Proxy(obj, { 
    get: function(target, prop) { 
    console.log({ type: 'get', target, prop }); 
    return Reflect.get(target, prop); 
    }, 
    set: function(target, prop, value) { 
    console.log({ type: 'set', target, prop, value }); 
    return Reflect.set(target, prop, value); 
    } 
}); 

proxied.bar = 2; 
// {type: 'set', target: <obj>, prop: 'bar', value: 2} 

proxied.foo; 
// {type: 'get', target: <obj>, prop: 'bar'} 
+1

Cảm ơn Dan, tôi đang cố gắng chạy ví dụ đầu tiên nó đang chạy vòng lặp infinte. Tôi đang chạy ví dụ này trong chrome 48.x – Shad

+0

Rất tiếc. Thiếu một dấu gạch dưới. –

+0

@ Có thể khi Chad đề cập đến soln đầu tiên của bạn đang chạy vòng lặp vô hạn. – Nirus

10

@Dan solution là đúng.

Trong trường hợp nếu bạn muốn hỗ trợ các trình duyệt cũ hơn, tôi khuyên bạn nên truy cập polyfill.

hoặc sử dụng Object.defineProperties API được hỗ trợ trong IE 9.

var obj = Object.defineProperties({}, { 
    "foo":{ 
     get:function(){ 
      console.log("Get:"+this.value); 
     }, 
     set:function(val){ 
      console.log("Set:"+val); 
      this.value = val; 
     } 
    }, 

    "bar":{   
     get:function(){ 
      console.log("Get:"+this.value); 
     }, 
     set:function(val){ 
      console.log("Set:"+val); 
      this.value = val; 
     } 
    } 
}); 
5

Disclaimer: Tôi là tác giả của thư viện object-observer gợi ý dưới đây.

Tôi không đi với giải pháp getters/setters - nó phức tạp, không thể mở rộng và không thể duy trì. Backbone đã ràng buộc hai chiều của họ theo cách đó và bản mẫu để làm cho nó hoạt động chính xác là một đoạn mã.

Proxy là cách tốt nhất để đạt được những gì bạn cần, chỉ cần thêm vào các ví dụ ở trên một số đăng ký và quản lý cuộc gọi lại và thực hiện chúng khi có thay đổi.

Liên quan đến thư viện polyfill: một số/hầu hết trong số này được triển khai bằng cách sử dụng 'kiểm tra bẩn' hoặc kỹ thuật bỏ phiếu - không hiệu quả, không thực hiện. Thỉnh thoảng, đây là trường hợp của polyfill được chỉ ra bởi Nirus ở trên.

Tôi khuyên bạn nên chọn một số thư viện quan sát qua Proxy. Có một vài trong số đó, object-observer là một trong số chúng: được viết cho trường hợp sử dụng này chính xác, sử dụng các proxy gốc, cung cấp quan sát cây sâu, v.v.

+0

Còn hỗ trợ trình duyệt thì sao? [** Các proxy không thể được xếp chồng hoặc xếp chồng **] (https://stackoverflow.com/questions/35025204/javascript-proxy-support-in-babel), vì vậy IMO sử dụng Proxy không thực sự là một ý tưởng hay môi trường sản xuất chưa! –

+0

Phải, triển khai này sẽ không chạy trên bất kỳ môi trường nào không hỗ trợ đối tượng Proxy. Tuy nhiên, tất cả các trình duyệt chính có thể tải xuống đều đã có (Chrome, Firefox, Opera) và thực sự là Edge. Các phiên bản di động cũng có sẵn. Vì vậy, mối quan tâm duy nhất tôi có thể thấy là IE trước Edge - tốt, cá nhân tôi đã để lại nó phía sau. – GullerYA

+0

Trong thế giới công ty, việc giảm hỗ trợ IE thường không phải là một lựa chọn. –

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