2009-02-02 38 views
76

Trước đây, khi tôi cần lưu trữ một số biến có liên quan, tôi sẽ tạo một lớp.Cấu trúc trong Javascript

function Item(id, speaker, country) { 
    this.id = id; 
    this.speaker = spkr; 
    this.country = country; 
} 
var myItems = [ 
    new Item(1, 'john', 'au'), 
    new Item(2, 'mary', 'us') 
]; 

Nhưng tôi tự hỏi đây có phải là phương pháp hay hay không. Có cách nào khác, tốt hơn cách để mô phỏng cấu trúc trong Javascript không?

Trả lời

145

Sự khác biệt duy nhất giữa các đối tượng literals và các đối tượng được xây dựng là các thuộc tính được thừa kế từ nguyên mẫu.

var o = { 
    'a': 3, 'b': 4, 
    'doStuff': function() { 
    alert(this.a + this.b); 
    } 
}; 
o.doStuff(); // displays: 7 

Bạn có thể làm cho một nhà máy struct.

function makeStruct(names) { 
    var names = names.split(' '); 
    var count = names.length; 
    function constructor() { 
    for (var i = 0; i < count; i++) { 
     this[names[i]] = arguments[i]; 
    } 
    } 
    return constructor; 
} 

var Item = makeStruct("id speaker country"); 
var row = new Item(1, 'john', 'au'); 
alert(row.speaker); // displays: john 
+14

... và sau đó tôi hiểu các chức năng của nhà máy. 1 cho câu trả lời rõ ràng, dễ hiểu và ngắn gọn, cùng với ví dụ về nhà máy. – John

+0

Tôi thích cách tiếp cận này, tuy nhiên hãy cẩn thận nếu bạn sử dụng trình biên dịch đóng. Bộ tuple chỉ có thể được truy cập dưới dạng chuỗi trong trường hợp này, bởi vì các thuộc tính được đổi tên. (Ít nhất là ở chế độ nâng cao) – kap

24

tôi luôn luôn sử dụng đối tượng trực

{id: 1, speaker:"john", country: "au"} 
+1

sẽ không mà làm cho nó khó khăn hơn nhiều để duy trì (nên bạn muốn thêm một lĩnh vực mới trong tương lai), và cũng nhiều hơn nữa mã (retyping "id", "loa", "quốc gia" mỗi lần)? – nickf

+4

Nó chính xác như là giải pháp với các lớp vì JavaScript không quan tâm đến số đối số mà bạn gọi hàm. Nhập lại không phải là vấn đề nếu bạn sử dụng các công cụ thích hợp như Emacs. Và bạn có thể thấy những gì tương đương với những gì làm cho những sai lầm như hoán đổi các đối số đã lỗi thời. – vava

+3

Nhưng chuyên gia lớn nhất là bạn sẽ viết ít mã hơn và nó sẽ sạch hơn :) – vava

2

tôi sử dụng đối tượng JSON phong cách cho struct câm (không có chức năng thành viên).

7

Tôi nghĩ rằng việc tạo ra một lớp học để mô phỏng cấu trúc của C-like, như bạn đã làm, là tốt nhất cách.

Đây là cách tuyệt vời để nhóm dữ liệu có liên quan và đơn giản hóa các tham số truyền cho các hàm. Tôi cũng cho rằng một lớp JavaScript giống như một cấu trúc C++ hơn một lớp C++, xem xét added effort cần thiết để mô phỏng các đối tượng hướng đối tượng thực sự.

Tôi nhận thấy rằng việc cố gắng làm cho JavaScript giống một ngôn ngữ khác trở nên phức tạp nhanh chóng, nhưng tôi hoàn toàn hỗ trợ sử dụng các lớp JavaScript làm cấu trúc không có chức năng.

+0

Tôi muốn có thứ gì đó như cấu trúc, bộ dữ liệu - thứ gì đó cho phép thu thập dữ liệu mạnh mẽ - được xử lý ở chế độ compiletime và không có chi phí của hashmaps như đối tượng – derekdreery

9

Vấn đề thực sự là cấu trúc trong ngôn ngữ được coi là loại giá trị không phải là loại tham chiếu. Các câu trả lời được đề xuất đề xuất sử dụng các đối tượng (là các kiểu tham chiếu) thay cho các cấu trúc. Trong khi điều này có thể phục vụ cho mục đích của nó, nó vượt qua điểm mà một lập trình viên thực sự muốn những lợi ích của việc sử dụng các loại giá trị (như một nguyên thủy) thay cho kiểu tham chiếu. Loại giá trị, cho một, không nên gây rò rỉ bộ nhớ.

1

Sau Markus của answer, trong các phiên bản mới hơn của JS (ES6 tôi nghĩ), bạn có thể tạo một nhà máy 'struct' đơn giản hơn sử dụng Arrow FunctionsRest Parameter như vậy:

const Struct = (...keys) => ((...v) => keys.reduce((o, k, i) => {o[k] = v[i]; return o} , {})) 
const Item = Struct('id', 'speaker', 'country') 
var myItems = [ 
    Item(1, 'john', 'au'), 
    Item(2, 'mary', 'us') 
]; 

console.log(myItems); 
console.log(myItems[0].id); 
console.log(myItems[0].speaker); 
console.log(myItems[0].country); 

Kết quả của hoạt động này là:

[ { id: 1, speaker: 'john', country: 'au' }, 
    { id: 2, speaker: 'mary', country: 'us' } ] 
1 
john 
au 

Bạn có thể làm cho nó trông giống như namedtuple Python:

const NamedStruct = (name, ...keys) => ((...v) => keys.reduce((o, k, i) => {o[k] = v[i]; return o} , {_name: name})) 
const Item = NamedStruct('Item', 'id', 'speaker', 'country') 
var myItems = [ 
    Item(1, 'john', 'au'), 
    Item(2, 'mary', 'us') 
]; 

console.log(myItems); 
console.log(myItems[0].id); 
console.log(myItems[0].speaker); 
console.log(myItems[0].country); 

Và kết quả:

[ { _name: 'Item', id: 1, speaker: 'john', country: 'au' }, 
    { _name: 'Item', id: 2, speaker: 'mary', country: 'us' } ] 
1 
john 
au 
0

tôi đã thực hiện một thư viện nhỏ để xác định cấu trúc nếu bạn làm việc với khả năng tương thích ES6.

Đó là một phân tích cú pháp JKT bạn có thể kiểm tra các kho dự án ở đây JKT Parser

Đối với một ví dụ bạn có thể tạo ra cấu trúc của bạn như thế này

const Person = jkt` 
    name: String 
    age: Number 
` 

const someVar = Person({ name: "Aditya", age: "26" }) 

someVar.name // print "Aditya" 
someVar.age // print 26 (integer) 

someVar.toJSON() // produce json object with defined schema 
Các vấn đề liên quan