Số phần tử trong một đối tượng javascript


103

Có cách nào để lấy (từ đâu đó) số phần tử trong một đối tượng javascript không ?? (tức là độ phức tạp theo thời gian không đổi).

Tôi không thể tìm thấy thuộc tính hoặc phương pháp truy xuất thông tin đó. Cho đến nay tôi chỉ có thể nghĩ đến việc lặp lại toàn bộ bộ sưu tập, nhưng đó là thời gian tuyến tính.
Thật kỳ lạ là không có quyền truy cập trực tiếp vào kích thước của đối tượng, bạn không nghĩ vậy.

CHỈNH SỬA:
Tôi đang nói về Objectđối tượng (không phải đối tượng nói chung):

var obj = new Object ;

5
Đã trả lời ở đây stackoverflow.com/questions/126100/... Object.keys (obj) .length
spats

Câu trả lời:


155

Mặc dù các triển khai JS có thể theo dõi một giá trị như vậy trong nội bộ, nhưng không có cách tiêu chuẩn nào để lấy nó.

Trước đây, biến thể Javascript của Mozilla có lỗi không chuẩn__count__ , nhưng nó đã bị loại bỏ với phiên bản 1.8.5.

Đối với tập lệnh trên nhiều trình duyệt, bạn gặp khó khăn với việc lặp lại rõ ràng các thuộc tính và kiểm tra hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

Trong trường hợp có khả năng triển khai ECMAScript 5, điều này cũng có thể được viết là (Kudos to Avi Flax )

function countProperties(obj) {
    return Object.keys(obj).length;
}

Hãy nhớ rằng bạn cũng sẽ bỏ lỡ các thuộc tính không thể liệt kê được (ví dụ: của một mảng length).

Nếu bạn đang sử dụng một khuôn khổ như jQuery, Prototype, Mootools, $ any-the-newest-hype, hãy kiểm tra xem chúng có đi kèm với API bộ sưu tập của riêng chúng hay không, đây có thể là giải pháp tốt hơn cho vấn đề của bạn so với việc sử dụng các đối tượng JS gốc.


11
Chết tiệt thật, tôi luôn quên hasOwnProperty. Tôi nói với bạn quá nhiều thời gian ở vùng đất .NET. +1
annakata

2
jQuery sử dụng một đối tượng cho các bộ sưu tập của nó mà nó nhận được từ các truy vấn và nó hiển thị giá trị đó với thuộc tính length.
Nosredna

6
Firefox4 __count__đã biến mất :(
Timo Huovinen

1
Có cách nào để làm điều này mà không cần cho vào không? Tôi đang ở cùng một loại ràng buộc nhưng tôi muốn làm cho nó vượt qua JSLint nếu có thể.
đèn đường vào

1
tại sao chúng ta cần hasOwnProperty()?
swisswiss

99

Để thực hiện việc này trong mọi môi trường tương thích với ES5

Object.keys(obj).length

(Hỗ trợ trình duyệt từ đây )
(Tài liệu trên Object.keys tại đây , bao gồm phương pháp bạn có thể thêm vào các trình duyệt không phải ECMA5)


2
Đây không phải là câu hỏi phù hợp để đặt câu trả lời này. Cùng với đó, bạn đang lấy tất cả các khóa của đối tượng, đặt chúng vào một mảng mới được tạo và sau đó truy xuất thuộc tính độ dài từ mảng mới đó.
GetFree

11
Nó có thể không hiệu quả nhất về mặt lập trình, nhưng nó là hiệu quả nhất dành cho nhà phát triển.
siêu thường

9

nếu bạn đang sử dụng jQuery trong bản dựng của mình, chỉ cần thực hiện điều này:

$(yourObject).length

Nó hoạt động tốt đối với tôi trên các đối tượng và tôi đã có jQuery như một phụ thuộc.


5
Kỳ lạ ... điều này không hiệu quả với tôi. Tôi luôn nhận được 1. Câu trả lời của ZelkiN phù hợp với tôi.
mike Rodent

3
Mã này luôn trả về 1. Chỉ 1 đối tượng. Nó không tính các phần tử trong đó
BeRocket

5
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);

2

AFAIK, không có cách nào để làm điều này một cách đáng tin cậy, trừ khi bạn chuyển sang một mảng. Thành thật mà nói, không có vẻ gì là lạ - đối với tôi thì có vẻ khá dễ hiểu rằng các mảng có thể đếm được còn các đối tượng thì không.

Có lẽ điều gần nhất bạn sẽ nhận được là một cái gì đó như thế này

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

Nhưng điều này tạo ra vấn đề, hoặc ít nhất là câu hỏi. Tất cả các thuộc tính do người dùng tạo đều được tính, bao gồm cả chính hàm _length! Và trong khi trong ví dụ đơn giản này, bạn có thể tránh nó bằng cách chỉ sử dụng một hàm bình thường, điều đó không có nghĩa là bạn có thể ngăn các tập lệnh khác thực hiện việc này. vậy bạn làm gì? Bỏ qua thuộc tính hàm?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

Cuối cùng, tôi nghĩ bạn có lẽ nên bỏ ý tưởng làm cho các đối tượng của bạn có thể đếm được và tìm ra một cách khác để làm bất cứ điều gì bạn đang làm.


8
NGUY HIỂM SẼ ROBINSON! Làm KHÔNG proto chống lại đối tượng! Mọi thứ đi xuống từ Object, bạn sẽ làm tê liệt quá trình xử lý của khách hàng như thế này nếu bạn đang thực hiện bất kỳ công việc JS nào.
annakata

5
Uh ... bạn đã không đọc đoạn mà tôi viết trong một bình luận "Khỉ vá víu có chủ ý" - thôi, tôi cố tình làm vậy để mọi người không lật tẩy một chút về nó. Bên cạnh đó, mặc dù tôi không ủng hộ việc vá lỗi khỉ, nhưng bạn hiểu sai cách chuỗi nguyên mẫu hoạt động trong Javascript nếu bạn nghĩ rằng điều này sẽ gây ra các vấn đề về hiệu suất video.yahoo.com/watch/111585/1027823
Peter Bailey

Vì vậy .. đây là nên làm hay không?
OscarRyz

Trong "Javascript: The Good Parts", anh ta tạo nguyên mẫu đối tượng bằng phương thức "create ()". Tôi tin rằng đó là cuốn sách định nghĩa về Javascript.
Chris Dutrow

1

Khái niệm số / chiều dài / chiều không thực sự có ý nghĩa đối với một Đối tượng, và cần nó cho thấy bạn thực sự muốn có Mảng đối với tôi.

Chỉnh sửa: Chỉ ra với tôi rằng bạn muốn có điểm O (1) cho điều này. Theo sự hiểu biết của tôi, tôi e rằng không có cách nào như vậy tồn tại.


Anh ấy đề xuất lặp lại chính mình, giải pháp này là. Anh ấy cần một cách O (1) để đạt được điều này ...
Thomas Hansen

Bạn khá đúng. Thực sự nên đọc câu hỏi kỹ lưỡng hơn.
annakata

Trên thực tế, Đối tượng là thứ gần nhất với Bản đồ trong JS. Bản đồ có chiều dài.
Cristian Vrabie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.