วิธีการนับจำนวนคีย์ / คุณสมบัติของวัตถุใน JavaScript อย่างมีประสิทธิภาพ


1544

วิธีที่เร็วที่สุดในการนับจำนวนคีย์ / คุณสมบัติของวัตถุคืออะไร เป็นไปได้ไหมที่จะทำได้โดยไม่ต้องวนซ้ำวัตถุ? ie โดยไม่ต้องทำ

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;

(Firefox ให้__count__คุณสมบัติที่เป็นเวทมนตร์แต่สิ่งนี้ถูกลบออกไปรอบ ๆ เวอร์ชัน 4)


3
ที่เกี่ยวข้อง: stackoverflow.com/questions/5223/…
ripper234

2
มาตรฐานประสิทธิภาพสำหรับวิธีการต่าง ๆ : jsben.ch/#/oSt2p
EscapeNetscape

1
มีความเป็นไปได้ที่ซ้ำกันของความยาวของวัตถุ JavaScript
Adam Katz

คำตอบ:


2516

หากต้องการทำสิ่งนี้ในสภาพแวดล้อมที่รองรับ ES5เช่นNode , Chrome, IE 9+, Firefox 4+ หรือ Safari 5+:

Object.keys(obj).length

8
ไม่ใช่แค่ Node.js แต่สภาพแวดล้อมใด ๆ ที่รองรับ ES5
Yi Jiang

59
BTW ... เพิ่งทำการทดสอบบางอย่าง ... วิธีนี้ทำงานในเวลา O (n) ห่วงสำหรับไม่ได้เลวร้ายยิ่งกว่าวิธีนี้ ** หน้าเศร้า ** stackoverflow.com/questions/7956554/…
BMiner

161
-1 (-200 ถ้าฉันทำได้) นี่ไม่เพียง แต่ทำซ้ำผ่านวัตถุ แต่ยังสร้างอาร์เรย์ใหม่ทั้งหมดพร้อมคีย์ทั้งหมดดังนั้นจึงล้มเหลวอย่างสิ้นเชิงเมื่อตอบคำถาม
GetFree

42
ดูเหมือนว่าจะเร็วกว่าการทำเพื่อ (อย่างน้อยใน Chrome 25): jsperf.com/count-elements-in-object
fserb

34
@ GetFree ทำไมต้องยกนิ้วให้มากมาย? นี่เป็นวิธีที่เร็วที่สุดในการเขียนโปรแกรม ไม่ต้องใช้วิธีการหรือไลบรารีพิเศษ ในแง่ของความเร็วโค้ดเห็นได้ชัดว่ามันไม่ได้แย่เกินไปเช่นกัน ไม่ล้มเหลวทั้งหมด 87 ยกนิ้วล้มเหลวสำหรับคุณ
Andrew

150

คุณสามารถใช้รหัสนี้:

if (!Object.keys) {
    Object.keys = function (obj) {
        var keys = [],
            k;
        for (k in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, k)) {
                keys.push(k);
            }
        }
        return keys;
    };
}

จากนั้นคุณสามารถใช้สิ่งนี้ในเบราว์เซอร์รุ่นเก่าเช่นกัน:

var len = Object.keys(obj).length;

2
จุดประสงค์ของการตรวจสอบ(Object.prototype.hasOwnProperty.call(obj, k))คืออะไร?
สไตล์

14
@styfle ถ้าคุณใช้สำหรับวงย้ำกว่าคุณสมบัติของวัตถุที่คุณยังได้รับคุณสมบัติในห่วงโซ่ต้นแบบ นั่นเป็นเหตุผลที่การตรวจสอบhasOwnPropertyเป็นสิ่งที่จำเป็น มันจะส่งกลับคุณสมบัติที่ตั้งค่าไว้บนวัตถุเท่านั้น
Renaat De Muynck

13
@styfle เพื่อให้ง่ายขึ้นคุณสามารถเขียนobj.hasOwnProperty(k)(จริง ๆ แล้วฉันทำในโพสต์ต้นฉบับของฉัน แต่ปรับปรุงในภายหลัง) hasOwnPropertyสามารถใช้ได้กับทุกวัตถุเพราะเป็นส่วนหนึ่งของObjectต้นแบบ แต่ในเหตุการณ์ที่หายากว่าวิธีนี้จะถูกลบหรือแทนที่คุณอาจได้รับผลลัพธ์ที่ไม่คาดคิด โดยเรียกมันจากObject.prototypeมันทำให้แข็งแกร่งขึ้นเล็กน้อย เหตุผลในการใช้งานcallเป็นเพราะคุณต้องการเรียกใช้เมธอดobjแทนบนต้นแบบ
Renaat De Muynck

6
จะดีกว่าไหมถ้าใช้รุ่นนี้ developer.mozilla.org/en-US/docs/JavaScript/Reference/ …
Xavier Delamotte

1
@XavierDelamotte คุณถูกต้องจริงๆ ในขณะที่รุ่นของฉันใช้งานได้มันเป็นพื้นฐานและเป็นตัวอย่าง รหัสของ Mozilla ปลอดภัยกว่า (PS: ลิงก์ของคุณเป็นคำตอบที่ยอมรับเช่นกัน)
Renaat De Muynck

137

หากคุณใช้Underscore.jsคุณสามารถใช้_.size (ขอบคุณ @douwe):
_.size(obj)

หรือคุณสามารถใช้_.keysซึ่งอาจชัดเจนสำหรับบางคน:
_.keys(obj).length

ฉันขอแนะนำ Underscore เป็นห้องสมุดที่แน่นสำหรับการทำสิ่งพื้นฐานมากมาย เมื่อใดก็ตามที่เป็นไปได้พวกเขาจะจับคู่ ECMA5 และเลื่อนไปสู่การปฏิบัติตามท้องถิ่น

มิฉะนั้นฉันจะสนับสนุนคำตอบของ @ Avi ฉันแก้ไขมันเพื่อเพิ่มลิงค์ไปยัง MDC doc ซึ่งมีปุ่ม () วิธีการที่คุณสามารถเพิ่มไปยังเบราว์เซอร์ที่ไม่ใช่ ECMA5


9
หากคุณใช้ underscore.js คุณควรใช้ _.size แทน สิ่งที่ดีคือถ้าคุณสลับจากอาเรย์เป็นวัตถุหรือในทางกลับกันผลลัพธ์จะยังคงเหมือนเดิม
douwe

2
และจากความเข้าใจของฉัน lodash โดยทั่วไปจะดีกว่าขีดล่าง (แม้ว่าพวกเขาจะทำสิ่งที่คล้ายกัน)
Merlyn Morgan-Graham

1
@ MerlynMorgan-Graham ถ้าฉันจำได้ถูกต้อง Lodash เป็นทางแยกของขีดเส้นใต้ ...
molson504x

6
_.keys(obj).lengthทำงานได้ดีที่สุดสำหรับฉันเพราะบางครั้งวัตถุส่งคืนของฉันอาจเป็นสตริงธรรมดาที่ไม่มีคุณสมบัติอยู่ภายใน _.size(obj)ให้ความยาวของสตริง_.keys(obj).lengthกลับในขณะที่ส่งคืน 0
Jacob Stamm

O (n) ความซับซ้อน Lodash และขีดObject.keysล่างใช้ภายใน ขีดล่างจะคัดลอกทุกคีย์ลงในอาร์เรย์ภายในfor..inลูปหากObject.keysไม่ได้กำหนดไว้
N. Kudryavtsev

82

การใช้งานวัตถุมาตรฐาน ( คุณสมบัติและวิธีการภายในวัตถุของ ES5.1 ) ไม่จำเป็นต้องมีObjectการติดตามจำนวนของคีย์ / คุณสมบัติดังนั้นจึงไม่มีวิธีมาตรฐานในการกำหนดขนาดของObjectโดยไม่มีการวนซ้ำอย่างชัดเจนหรือโดยปริยาย

ดังนั้นนี่คือทางเลือกที่ใช้บ่อยที่สุด:

1. Object.keys ของ ECMAScript ()

Object.keys(obj).length;ทำงานโดยการวนซ้ำภายในคีย์เพื่อคำนวณอาร์เรย์ชั่วคราวและส่งคืนความยาว

  • ข้อดี - ไวยากรณ์ที่อ่านได้และทำความสะอาด ไม่จำเป็นต้องใช้ไลบรารีหรือรหัสที่กำหนดเองยกเว้น shim หากการสนับสนุนดั้งเดิมไม่พร้อมใช้งาน
  • Cons - โอเวอร์เฮดหน่วยความจำเนื่องจากการสร้างอาเรย์

2. โซลูชันบนห้องสมุด

ตัวอย่างจากห้องสมุดหลายแห่งในหัวข้อนี้เป็นสำนวนที่มีประโยชน์ในบริบทของห้องสมุด อย่างไรก็ตามจากมุมมองประสิทธิภาพการทำงานไม่มีอะไรที่จะได้รับเมื่อเทียบกับโค้ดที่ไม่มีไลบรารีที่สมบูรณ์แบบเนื่องจากเมธอดไลบรารีทั้งหมดนั้นห่อหุ้มแบบ for-loop หรือ ES5 Object.keys(native หรือ shimmed)

3. การปรับให้เหมาะสมสำหรับ for-loop

ส่วนที่ช้าที่สุดของ for-loop นั้นโดยทั่วไปแล้วเป็นการ.hasOwnProperty()เรียกเนื่องจากการเรียกใช้ฟังก์ชัน ดังนั้นเมื่อผมต้องการเพียงแค่จำนวนของรายการของวัตถุ JSON ที่ฉันเพิ่งข้ามโทรถ้าฉันรู้ว่ารหัสไม่ได้หรือจะขยาย.hasOwnProperty() Object.prototype

มิฉะนั้นรหัสของคุณอาจได้รับการปรับให้เหมาะสมเล็กน้อยโดยการกำหนดklocal ( var k) และโดยใช้ตัวดำเนินการเพิ่มคำนำหน้า ( ++count) แทน postfix

var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

ความคิดอื่นอาศัยการแคชhasOwnPropertyเมธอด:

var hasOwn = Object.prototype.hasOwnProperty;
var count = 0;
for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

ไม่ว่าจะเร็วกว่านี้หรือไม่ในสภาพแวดล้อมที่กำหนดเป็นคำถามของการเปรียบเทียบ สามารถเพิ่มประสิทธิภาพที่ จำกัด ได้อย่างมาก


ทำไมต้องvar k in myobjเพิ่มประสิทธิภาพ เท่าที่ฉันรู้เฉพาะฟังก์ชั่นประกาศขอบเขตใหม่ใน JavaScript ข้อผิดพลาดในกฎนี้มีการวนซ้ำหรือไม่
Lars Gyrup Brink Nielsen

1
เร็วกว่านี้ไหม for (var k in myobj) hasOwn.call(myobj, k) && ++count;คือการแทนที่คำสั่ง if ด้วยคำว่า && ที่เรียบง่าย?
Hamza Kubba

สิ่งสุดท้ายที่คุณสามารถทำได้: Object.getOwnPropertyNames(obj).length; ง่ายกว่ามาก
ร่วงหล่น

29

หากคุณกำลังประสบปัญหาประสิทธิภาพการทำงานจริง ๆ ฉันขอแนะนำให้ตัดการเรียกที่เพิ่ม / ลบคุณสมบัติไปยัง / จากวัตถุด้วยฟังก์ชันที่เพิ่มขึ้น / ลดลงคุณสมบัติ (ขนาด?) ที่มีชื่อเหมาะสม

คุณจำเป็นต้องคำนวณจำนวนคุณสมบัติเริ่มต้นเพียงครั้งเดียวและดำเนินการต่อจากที่นั่น หากไม่มีปัญหาประสิทธิภาพที่แท้จริงไม่ต้องกังวล เพียงห่อโค้ดนั้นไว้ในฟังก์ชันgetNumberOfProperties(object)และใช้งาน


4
@ hitautodestruct เพราะเขามีทางออก
สนใจ

@ crush คำตอบนี้ดูเหมือนจะแนะนำสิ่งที่ต้องทำมากกว่าให้วิธีแก้ปัญหาโดยตรง
hitautodestruct

5
@ hitautodestruct มันแนะนำคำตอบ: การเพิ่ม / ลดจำนวน encapsulated ด้วยวิธีการเพิ่ม / ลบ มีคำตอบอื่นตรงกับด้านล่างนี้ ความแตกต่างเพียงอย่างเดียวคือความสับสนไม่ได้เสนอรหัสใด ๆ รู้รอบไม่ได้รับคำสั่งให้แก้ปัญหารหัสเท่านั้น
สนใจ

1
มันอาจจะไม่สมบูรณ์แบบ ... แต่เมื่อเทียบกับ "คำตอบ" อื่น ๆ นี่อาจเป็นทางออกที่ดีที่สุดสำหรับบางสถานการณ์
d.raev

1
จนถึงตอนนี้เป็นทางออกเดียวที่ฉันเห็นว่าเป็น O (1) ความซับซ้อนของประสิทธิภาพเวลาคงที่อย่างต่อเนื่องและดังนั้นจึงเป็นทางออกเดียวที่ตอบรายละเอียดคำถามของ "ไม่ต้องวนซ้ำ" และควรเป็นคำตอบที่ยอมรับ ส่วนใหญ่ถ้าไม่ใช่คำตอบอื่น ๆ ทั้งหมดจะไม่ตอบเพราะมันมีความซับซ้อนของเวลาเชิงเส้น O (n); ในกรณีนี้สำหรับโซลูชัน 1 บรรทัดที่เรียกใช้ฟังก์ชัน. key () เช่นการเรียกใช้ฟังก์ชันนั้นคือ O (n)
เซเลโป

17

ตามที่ระบุโดย Avi Flax https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

จะทำเคล็ดลับสำหรับทุกคุณสมบัตินับบนวัตถุของคุณ Object.getOwnPropertyNamesแต่ยังรวมถึงคุณสมบัติที่ไม่นับคุณแทนสามารถใช้ นี่คือความแตกต่าง:

var myObject = new Object();

Object.defineProperty(myObject, "nonEnumerableProp", {
  enumerable: false
});
Object.defineProperty(myObject, "enumerableProp", {
  enumerable: true
});

console.log(Object.getOwnPropertyNames(myObject).length); //outputs 2
console.log(Object.keys(myObject).length); //outputs 1

console.log(myObject.hasOwnProperty("nonEnumerableProp")); //outputs true
console.log(myObject.hasOwnProperty("enumerableProp")); //outputs true

console.log("nonEnumerableProp" in myObject); //outputs true
console.log("enumerableProp" in myObject); //outputs true

ตามที่ระบุไว้ที่นี่มีการสนับสนุนเบราว์เซอร์เช่นเดียวกับObject.keys

อย่างไรก็ตามในกรณีส่วนใหญ่คุณอาจไม่ต้องการรวมจำนวนที่ไม่นับในการดำเนินการเหล่านี้ แต่ก็เป็นการดีที่จะทราบความแตกต่างเสมอ)


1
thumbs up สำหรับการกล่าวขวัญObject.getOwnPropertyNamesคุณเป็นเพียงคนเดียวที่นี่ ...
เหี่ยว

15

ฉันไม่ได้ตระหนักถึงวิธีการใด ๆ ที่จะทำเช่นนี้ แต่เพื่อให้การทำซ้ำให้น้อยที่สุดคุณสามารถลองตรวจสอบการมีอยู่ของ__count__และถ้ามันไม่มีอยู่ (เช่นไม่ใช่ Firefox) จากนั้นคุณสามารถทำซ้ำวัตถุและกำหนด เพื่อใช้ในภายหลังเช่น:

if (myobj.__count__ === undefined) {
  myobj.__count__ = ...
}

วิธีนี้เบราว์เซอร์ที่รองรับ__count__จะใช้สิ่งนั้นและจะมีการทำซ้ำสำหรับผู้ที่ไม่ได้ทำเท่านั้น หากการนับมีการเปลี่ยนแปลงและคุณไม่สามารถทำได้คุณสามารถทำให้เป็นฟังก์ชันได้เสมอ:

if (myobj.__count__ === undefined) {
  myobj.__count__ = function() { return ... }
  myobj.__count__.toString = function() { return this(); }
}

วิธีนี้ทุกเวลาที่คุณอ้างอิง myobj __count__ฟังก์ชั่นนี้จะทำการยิงและคำนวณใหม่


13
โปรดทราบว่าObject.prototype.__count__จะถูกลบใน Gecko 1.9.3: whereswalden.com/2010/04/06/.. นับจำนวน - คุณสมบัติของวัตถุ - กำลังถูกลบออก /
dshaw

17
ตอนนี้ Firefox 4 ออกแล้วคำตอบนี้ล้าสมัยไปแล้ว Object.__count__หายไปแล้วและมีการจัดการที่ดีเช่นกัน
Yi Jiang

1
ฉันจะไม่พูดคำตอบที่ล้าสมัย มันยังคงเป็นกลยุทธ์ที่น่าสนใจในการสรุปคุณค่าในฟังก์ชั่น
devios1

ควรใช้วัตถุต้นแบบเพื่อขยาย
Aaria Carter-Weir

13

ในการวนซ้ำบน Avi Flax ให้คำตอบ Object.keys (obj) ความยาวถูกต้องสำหรับวัตถุที่ไม่มีฟังก์ชั่นผูกอยู่กับมัน

ตัวอย่าง:

obj = {"lol": "what", owo: "pfft"};
Object.keys(obj).length; // should be 2

กับ

arr = [];
obj = {"lol": "what", owo: "pfft"};
obj.omg = function(){
    _.each(obj, function(a){
        arr.push(a);
    });
};
Object.keys(obj).length; // should be 3 because it looks like this 
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

ขั้นตอนเพื่อหลีกเลี่ยงปัญหานี้:

  1. อย่าใส่ฟังก์ชั่นในวัตถุที่คุณต้องการนับจำนวนของปุ่ม

  2. ใช้วัตถุที่แยกออกจากกันหรือสร้างวัตถุใหม่สำหรับฟังก์ชั่นโดยเฉพาะ (ถ้าคุณต้องการนับจำนวนฟังก์ชั่นที่มีในไฟล์ที่ใช้Object.keys(obj).length)

ใช่ฉันใช้ _ หรือขีดล่างโมดูลจาก nodejs ในตัวอย่างของฉัน

เอกสารสามารถพบได้ที่นี่http://underscorejs.org/เช่นเดียวกับแหล่งที่มาของ GitHub และข้อมูลอื่น ๆ อีกมากมาย

และในที่สุดก็ทำการติดตั้งhttps://lodash.com/docs#size

_.size(obj)


เพื่อตอบความคิดเห็นของคุณเกี่ยวกับArray(obj).length: มันไม่ทำงาน http://jsfiddle.net/Jhy8M/
Jamie Chong

ใช่ฉันดูเป็นมันมากขึ้นอีกนิด im จะจบลงด้วยการลบคำตอบนี้ถ้าเป็นไปได้หรือเพียงแค่การแก้ไขไว้ด้วยกัน
Belldandu

ฉันไม่เห็นว่าสิ่งนี้เกี่ยวข้องกับฟังก์ชั่นใดอย่างหนึ่งและใน Chrome ฉันไม่เห็นพฤติกรรมนี้เลย ฉันสงสัยว่าสิ่งนี้อาจเกี่ยวข้องกับพฤติกรรมเริ่มต้นของObject.defineProperty (): นับได้ซึ่งfalseถึงแม้ว่าฉันยังไม่พบเอกสารใด ๆ เกี่ยวกับวิธีการที่var obj = { a: true, b: true }อาจแตกต่างจากvar obj = {}; obj.a = true; obj.b = true;หรือถ้าการตีความ / ความหมายที่แตกต่างกันของ W3 มี ได้รับการรับรองจาก Chrome
Nolo

10

ตามคำตอบข้างต้น: Object.keys(obj).length

แต่: เนื่องจากเรามีคลาสMapจริงใน ES6 ฉันจึงแนะนำให้ใช้แทนการใช้คุณสมบัติของวัตถุ

const map = new Map();
map.set("key", "value");
map.size; // THE fastest way

8

สำหรับผู้ที่มี Underscore.js รวมอยู่ในโครงการของพวกเขาคุณสามารถทำได้:

_({a:'', b:''}).size() // => 2

หรือสไตล์การทำงาน:

_.size({a:'', b:''}) // => 2

8

ต่อไปนี้เป็นการทดสอบประสิทธิภาพสำหรับสามวิธี

https://jsperf.com/get-the-number-of-keys-in-an-object

Object.keys (). ความยาว

20,735การดำเนินงานต่อวินาที

ง่ายมากและเข้ากันได้ ทำงานได้อย่างรวดเร็วแต่มีราคาแพงเพราะมันจะสร้างคีย์ใหม่ซึ่งจะถูกโยนทิ้งไป

return Object.keys(objectToRead).length;

วนผ่านปุ่มต่างๆ

15,734การดำเนินงานต่อวินาที

let size=0;
for(let k in objectToRead) {
  size++
}
return size;

ช้าลงเล็กน้อย แต่ไม่มีที่ไหนใกล้กับการใช้หน่วยความจำดังนั้นจึงน่าจะดีกว่าถ้าคุณสนใจที่จะเพิ่มประสิทธิภาพสำหรับโทรศัพท์มือถือหรือเครื่องขนาดเล็กอื่น ๆ

การใช้แผนที่แทนวัตถุ

953,839,338การดำเนินงานต่อวินาที

return mapToRead.size;

โดยทั่วไปแผนที่จะติดตามขนาดของมันเองดังนั้นเราจึงเพิ่งคืนค่าฟิลด์ตัวเลข ไกลเร็วกว่าวิธีอื่นใด หากคุณมีการควบคุมวัตถุให้แปลงเป็นแผนที่แทน


6

จาก: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty (obj, prop, descriptor)

คุณสามารถเพิ่มลงในวัตถุทั้งหมดของคุณ:

Object.defineProperty(Object.prototype, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

หรือวัตถุเดียว:

var myObj = {};
Object.defineProperty(myObj, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

ตัวอย่าง:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "leaked@example.com";
myObj.length; //output: 2

เพิ่มด้วยวิธีนี้จะไม่ปรากฏในสำหรับ .. ในลูป:

for(var i in myObj) {
     console.log(i + ":" + myObj[i]);
}

เอาท์พุท:

name:John Doe
email:leaked@example.com

หมายเหตุ: มันไม่ทำงานใน <เบราว์เซอร์ <IE9


หากคุณกำลังจะขยายต้นแบบในตัวหรือ polyfill คุณสมบัติ (เช่น monkey-patch) โปรดทำอย่างถูกต้อง: เพื่อความเข้ากันได้ไปข้างหน้าให้ตรวจสอบว่าคุณสมบัติมีอยู่ก่อนจากนั้นทำให้คุณสมบัติไม่สามารถนับได้เพื่อให้กุญแจของตัวเอง ของวัตถุที่สร้างขึ้นจะไม่ปนเปื้อน สำหรับวิธีการใช้งานที่เกิดขึ้นจริง วิธีการ คำแนะนำของฉัน: ทำตามตัวอย่างเหล่านี้ซึ่งสาธิตวิธีการเพิ่มวิธีการทำงานที่ใกล้เคียงที่สุดเท่าที่เป็นไปได้เช่นวิธีการที่มีในตัว
user4642212

5

วิธีที่ฉันแก้ไขปัญหานี้คือการสร้างการใช้งานลิสต์พื้นฐานของตัวเองซึ่งเก็บบันทึกว่ามีไอเท็มจำนวนเท่าใดที่ถูกเก็บไว้ในวัตถุ มันง่ายมาก บางสิ่งเช่นนี้

function BasicList()
{
   var items = {};
   this.count = 0;

   this.add = function(index, item)
   {
      items[index] = item;
      this.count++;
   }

   this.remove = function (index)
   {
      delete items[index];
      this.count--;
   }

   this.get = function(index)
   {
      if (undefined === index)
        return items;
      else
        return items[index];
   }
}

1
ทางเลือกที่น่าสนใจ สิ่งนี้จะกำจัดค่าใช้จ่ายของฟังก์ชั่นการนับรวม แต่ค่าใช้จ่ายของการเรียกใช้ฟังก์ชันทุกครั้งที่คุณเพิ่มหรือลบองค์ประกอบซึ่งน่าเสียดายที่อาจแย่กว่านั้น ฉันเองใช้รายการดำเนินการดังกล่าวสำหรับการห่อหุ้มข้อมูลและวิธีการที่กำหนดเองที่สามารถให้เปรียบเทียบกับอาร์เรย์ธรรมดา แต่ไม่เมื่อฉันต้องการนับรายการที่รวดเร็ว
Luc125

1
ฉันชอบคำตอบของคุณ แต่ฉันก็เป็นผู้ลงคะแนนและคลิกอัปโหลดได้เช่นกัน สิ่งนี้นำเสนอความกระอักกระอ่วนที่น่าสนใจ คุณไม่ได้คำนึงถึงพฤติกรรมบางอย่างในคำแนะนำของคุณเช่นสถานการณ์ของฉันที่ฉันได้ตอบคำถามของคุณแล้ว แต่ฉันได้รับคำแนะนำให้ "คลิกโหวต" และไม่สามารถทำได้ การเรียนการสอนล้มเหลวอย่างเงียบ ๆ แต่ฉันรวบรวมจากเนื้อหาของคุณที่นี่บนดังนั้นการล้มเหลวอย่างเงียบ ๆ ไม่ใช่สิ่งที่คุณต้องการให้โค้ดของคุณทำ แค่หัวขึ้น
L0j1k

1
ฉันชอบคำตอบนี้โครงสร้างข้อมูลที่ดี และถ้ามีผลกระทบต่อประสิทธิภาพการทำงานเมื่อมีการเรียกใช้ฟังก์ชั่นการเพิ่มจะมีการเพิ่มประสิทธิภาพมากขึ้นถ้าต้องทำซ้ำกับวัตถุ สิ่งนี้จะช่วยให้เสื้อวงเร็วที่สุดvar i = basiclist.count while(i--){...}
Lex

รายการพื้นฐานอย่างน้อยควรมีการตรวจสอบขั้นพื้นฐานหรือไม่ เช่นเดียวกับการตรวจสอบว่าaddแทนที่รายการเก่าหรือremoveถูกเรียกด้วยดัชนีที่ไม่มีอยู่ นอกจากนี้ยังเป็นไปไม่ได้ที่จะตรวจสอบว่ารายการมีดัชนีที่ระบุหรือไม่ว่าundefinedเป็นค่ารายการที่ถูกต้อง
Robert

2
รายการควรจะสั่งซื้อและ iterable ข้อมูลถูกเก็บไว้ในวัตถุดังนั้นจึงไม่มีการรับประกันการเรียงลำดับขององค์ประกอบ คุณจะค้นหาความยาวของรายการที่มีรูในรายการได้อย่างไร this.count? ค่าดัชนีสูงสุด? หากคุณเคยเพิ่มสองรายการที่ดัชนีเดียวกันการนับจะเข้าสู่สถานะข้อผิดพลาด
Ultimate Gobblement

4

คุณสามารถใช้Object.keys(data).lengthเพื่อค้นหาความยาวของวัตถุ JSON ที่มีข้อมูลสำคัญ


3

สำหรับผู้ที่มี Ext JS 4 ในโครงการของพวกเขาคุณสามารถทำได้:

Ext.Object.getSize(myobj);

ข้อดีของการทำเช่นนี้คือมันจะทำงานบนเบราว์เซอร์ที่ใช้งานร่วมกันได้ Ext ทั้งหมด (รวม IE6-IE8) แต่ฉันเชื่อว่าเวลาใช้งานไม่ดีกว่า O (n) เช่นเดียวกับโซลูชันที่แนะนำอื่น ๆ



1

OP ไม่ได้ระบุว่าวัตถุนั้นเป็น nodeList หรือไม่หากเป็นเช่นนั้นคุณสามารถใช้วิธียาวกับมันโดยตรง ตัวอย่าง:

buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen'); 


-1

ฉันไม่คิดว่ามันเป็นไปได้ (อย่างน้อยก็ไม่ได้โดยไม่ต้องใช้ภายใน) และฉันไม่คิดว่าคุณจะได้รับผลประโยชน์มากนักจากการปรับให้เหมาะสม


2
คำตอบที่ยอมรับได้แสดงให้เห็นว่าสิ่งนี้สามารถทำได้และคุณไม่มีบริบทที่จะยืนยันว่าไม่มีอะไรที่จะได้รับ
ราง

-1

ฉันพยายามทำให้วัตถุทั้งหมดเป็นเช่นนี้:

Object.defineProperty(Object.prototype, "length", {
get() {
    if (!Object.keys) {
        Object.keys = function (obj) {
            var keys = [],k;
            for (k in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, k)) {
                    keys.push(k);
                }
            }
            return keys;
        };
    }
    return Object.keys(this).length;
},});

console.log({"Name":"Joe","Age":26}.length) //returns 2

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.