2015-09-13 13 views
7

Tôi đang làm việc thông qua The Principles of Object-Oriented Javascript và bị nhầm lẫn với việc Zakas sử dụng một khóa có tên trong một mảng (trái ngược với bên trong một đối tượng). Xem nhận xét:Sử dụng các khóa được đặt tên trong một mảng JS

function EventTarget() {} 

EventTarget.prototype = { 

    constructor: EventTarget, 

    addListener: function(type, listener) { 

     if (!this.hasOwnProperty("_listeners")) { 
      // Why isn't this: `this._listeners = {};` 
      this._listeners = []; 
     } 

     if (typeof this._listeners[type] === "undefined") { 
      this._listeners[type] = []; 
     } 

     this._listeners[type].push(listener); 
    }, 

    // more stuff 
} 

var target = new EventTarget(); 
target.addListener("message", function(event) { 
    console.log("Message is " + event.data); 
}); 

Mã của anh ấy hoạt động tốt (như nếu bạn thay mảng cho đối tượng), nhưng hiểu biết của bạn là bạn nên sử dụng đối tượng nếu bạn muốn truy cập nội dung theo tên. Từ số array article on w3schools:

Nhiều ngôn ngữ lập trình hỗ trợ các mảng có chỉ mục được đặt tên.
Mảng có chỉ mục được đặt tên được gọi là mảng kết hợp (hoặc băm).
JavaScript không không hỗ trợ các mảng có chỉ mục được đặt tên.
Trong JavaScript, mảng luôn sử dụng chỉ mục được đánh số.

Có lý do chính đáng để Zakas sử dụng một mảng như thế này không? Bạn có thể giải thích nó không? Ngoài ra, đây có phải là điều tôi nên gửi đến the errata?

+0

Mã này là đúng nếu 'type' là số nguyên – hindmost

+0

Mã này vẫn hoạt động vì nó đang thiết lập các thuộc tính trên đối tượng mảng, không phải trong mảng thực tế. Kiểm tra 'Object.getOwnPropertyNames (this._listeners)' và sau đó là 'Object.keys (this._listeners)'. 'this._listeners' phải là một đối tượng, không phải là một mảng. – usandfriends

+0

@hindmost: Mã là chính xác (ở chỗ nó có chức năng) ngay cả khi 'type' * không phải là * một số nguyên (và có vẻ như nó sẽ không khả thi, nhiều khả năng là một chuỗi như' "click" '). –

Trả lời

5

Lý do duy nhất tôi có thể thấy là: người khó hiểu. JavaScript không thực thi bất cứ điều gì, thực sự, và vì mọi thứ đều là một đối tượng, bạn có thể làm khá nhiều thứ bạn muốn. Anh chàng này đang sử dụng một mảng để lưu trữ các thuộc tính có tên, nhưng anh ta rất có thể đã sử dụng một hàm hay bất cứ thứ gì khác!

Edit: gần tất cả mọi thứ là một đối tượng (nó sẽ xảy ra với tôi rằng ai đó có thể cố gắng thiết lập một tài sản trên undefined, kể từ khi một trong những lỗi phổ biến nhất trong JavaScript là TypeError : undefined is not an objectthở dài JavaScript, tại sao. bạn làm điều này với chúng ta?

+1

" mọi thứ đều là một đối tượng ". Không phải mọi thứ! – undefined

+1

Không xác định không phải là một đối tượng ... 'typeof undefined ===" undefined "' – usandfriends

2

có một lý do chính đáng mà Zakas sử dụng một mảng như thế này?

Từ mã niêm yết, tôi không thể nghĩ ra một, không có. Anh ấy không sử dụng f hành động mà _listeners đề cập đến một mảng. Nó thẳng thắn trông giống như một lỗi đánh máy. Vì nó hoạt động (vì các mảng thông thường của JavaScript là các đối tượng), lỗi đánh máy không bị bắt. Vâng, cho đến khi bạn bắt được nó. :-)

Trừ khi có một số mã bạn chưa trích dẫn, sau đó thêm mảng enries * vào mảng đó, không có lý do gì để sử dụng mảng đó (và cho là một vài lý do không).

* "mục nhập mảng" = thuộc tính có khóa là chỉ mục mảng . Vậy "chỉ mục mảng" là gì? "Tên thuộc tính chuỗi P là chỉ mục mảng nếu và chỉ khi ToString(ToUint32(P)) bằng P và ToUint32(P) không bằng 232−1." (spec)

2

Mảng chỉ là các đối tượng đặc biệt ....

a=[] 
a[7]=9 
a["abc"]=20 
a["xxx"]=30 
for (i in a) console.log("value",i,a[i]) 

Đầu ra;

value 7 9 
value abc 20 
value xxx 30 
0

tôi nghiêng để nói đó là một lỗi đánh máy nhưng trong off-cơ hội nó được dự định, thì sau đây là việc sử dụng hợp cụ thể chức năng duy nhất tôi có thể đưa ra ... (cảnh báo: thể chia ý kiến).

Cho rằng một mô hình quan sát viên/sự kiện là một khái niệm chung chung mà có thể được áp dụng cho bất kỳ đối tượng và "private" (biểu thị bằng dấu gạch chân) _listeners bất động sản có thể sẽ không bao giờ cần phải được biết về các mục tiêu - sau đó có thể lập luận rằng dữ liệu mà nó chứa là không cần thiết đối với chính đối tượng đó.

Điều đó có nghĩa là, có thể không mong muốn truyền loại dữ liệu này nếu đối tượng đích được tuần tự hóa. Ví dụ sau minh họa cách các JSON serializer bỏ qua các thuộc tính mảng không phải số trong foo.baz - tương tự như trong ví dụ của bạn, tất cả dữ liệu sự kiện kèm theo sẽ được gỡ bỏ:

var foo = { 
    bar: {}, 
    baz: [] 
}; 

foo.bar['p1'] = foo.baz['p1'] = 1; 
foo.bar['p2'] = foo.baz['p2'] = 2; 

console.log(JSON.stringify(foo)); // {"bar":{"p1":1,"p2":2},"baz":[]} 
Các vấn đề liên quan