2013-07-03 41 views
5

Tôi đang cố gắng xác định hàm toJSON không liệt kê trên đối tượng mẫu thử nghiệm mà không có nhiều may mắn. Tôi hy vọng một điều gì đó tương tự như ECMAScript 5 toJSON:JS chức năng không thể đếm được

Object.defineProperty(obj, prop, { enumerable: false }); 

Tuy nhiên điều này định nghĩa nó là tài sản không thể truy cập như một phương thức.

Tôi đã hy vọng để có thể xác định các chức năng trong một thời trang không đếm được, như tôi đã lên kế hoạch để xác định trong nguyên mẫu của tất cả các loại nguyên thủy (String, Number, Boolean, Array, và Object), vì vậy mà tôi có thể đệ quy áp dụng hàm thông qua các đối tượng phức tạp.

Mục tiêu cuối cùng ở đây là để có thể JSONify một mô hình/bộ sưu tập Backbone với các bộ sưu tập lồng nhau đệ quy.

Tôi đoán trong tổng Tôi có hai câu hỏi chính:

  1. Có thể định nghĩa một hàm phi đếm được trên một nguyên mẫu? Nếu thế thì sao?
  2. Có cách nào tốt hơn để JSONify các mô hình Backbone lồng nhau không?
+0

Phương thức theo định nghĩa * là * thuộc tính của đối tượng. Bạn đang vẽ một sự phân biệt không tồn tại. Nếu bạn muốn nó không được liệt kê, thì rõ ràng bạn đang liệt kê các thuộc tính của một đối tượng. –

+0

Có, tuy nhiên tôi muốn nó là một thuộc tính không thể đếm được, giống như cách mà Object.defineProperty không thể đếm được. tức là, không được lặp lại khi sử dụng 'for (x in obj) ' –

+0

Right. Một lần nữa, một phương thức là thuộc tính của một đối tượng tham chiếu đến một hàm. Mã bạn có là những gì bạn muốn sử dụng để làm cho thuộc tính không thể đếm được. –

Trả lời

13

Tôi không hiểu, tại sao bạn không thể truy cập nó dưới dạng phương thức?

var foo = {}; 

Object.defineProperty(foo, 'bar', { 
    enumerable: false, 
    value: function() {console.log('foo.bar\'d!');} 
}); 

foo.bar(); // foo.bar'd! 

Nếu bạn muốn nó trên nguyên mẫu, đó là dễ dàng như

Object.defineProperty(foo.prototype, /* etc */); 

hoặc thậm chí trực tiếp trong Object.create

foo.prototype = Object.create(null, { 
    'bar': {value: function() {/* ... */}} 
}); 

Tuy nhiên, trừ khi bạn đang tạo các trường hợp foo, nó sẽ không hiển thị nếu bạn cố gắng foo.bar và chỉ hiển thị là foo.prototype.bar.

Nếu foo có nguyên mẫu riêng (ví dụ: foo = Object.create({})), bạn có thể lấy nó bằng Object.getPrototypeOf, thêm thuộc tính vào đó và sau đó foo.bar sẽ hoạt động ngay cả khi đó không phải là một phiên bản.

var proto = Object.getPrototypeOf(foo); // get prototype 
Object.defineProperty(proto, /* etc */); 

Bạn có thể xem visibility of enumerable vs non-enumerable properties here.

+0

Tuyệt vời, cảm ơn!Vấn đề là tôi đã sử dụng 'get' thay vì' value', mà tôi không thể truy cập như một hàm. –

+0

_get_ gọi hàm _function_ mà không truyền bất kỳ đối số nào, sau đó giả vờ thuộc tính bằng với 'return' của hàm, vì vậy bạn đã làm' SJON() (args) 'khi bạn muốn thực hiện' SJON (args) ' –

+0

OK . Một câu hỏi cuối cùng nếu bạn không nhớ; cách tiếp cận này sẽ gây ra một số vấn đề tương tự như mở rộng các nguyên mẫu Object với một chức năng enumerable? –

1

Paul S. là đúng về việc cần thiết lập các định nghĩa tài sản của value thay vì một get, nhưng tôi muốn thêm rằng bạn không cần phải vượt qua enumerable: false, bởi vì sai lầm là mặc định cho tùy chọn đó trong Object.defineProperty() Câu trả lời có thể được đơn giản hóa thành:

var foo = {};  

Object.defineProperty(foo, 'bar', { 
    value: function(){ console.log('calling bar!'); } 
}); 

foo.bar(); 
+0

Cảm ơn, tôi chỉ đưa nó một cách rõ ràng để làm cho nó rõ ràng trong câu hỏi, nhưng đó là một lưu ý tốt rằng nó không thực sự cần thiết. –

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