etc./StackOverFlow

JavaScript에서 객체의 키/속성 수를 효율적으로 계산하는 방법

청렴결백한 만능 재주꾼 2022. 1. 5. 09:43
반응형

질문자 :mjs


개체의 키/속성 수를 계산하는 가장 빠른 방법은 무엇입니까? 객체를 반복하지 않고 이것을 할 수 있습니까? 즉, 하지 않고:

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

(Firefox는 마법의 __count__ 속성을 제공했지만 이것은 버전 4 부근에서 제거되었습니다.)



Node.js , Chrome, Internet Explorer 9+ , Firefox 4+ 또는 Safari 5+와 같은 ES5 호환 환경 에서 이 작업을 수행하려면:

 Object.keys(obj).length

Avi Flax

다음 코드를 사용할 수 있습니다.

 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;

Renaat De Muynck

Underscore.js 를 사용하는 경우 _.size 를 사용할 수 있습니다( 감사합니다 douwe ).

 _.size(obj)

또는 일부 경우 더 명확할 수 있는 _.keys를 사용할 수도 있습니다.

 _.keys(obj).length

Underscore.js를 적극 권장합니다. 많은 기본 작업을 수행하기 위한 빡빡한 라이브러리입니다. 가능할 때마다 ECMAScript 5 와 일치하고 기본 구현을 따릅니다.

그렇지 않으면 Avi Flax의 답변을 지원합니다. ECMAScript 5가 아닌 브라우저에 추가할 수 있는 keys() 메서드가 포함된 MDC 문서에 대한 링크를 추가하도록 편집했습니다.


studgeek

표준 개체 구현( ES5.1 개체 내부 속성 및 메서드 Object 가 키/속성의 수를 추적하도록 요구하지 않으므로 키를 명시적으로 또는 암시적으로 반복하지 않고 Object 의 크기를 결정하는 표준 방법이 없어야 합니다. .

따라서 가장 일반적으로 사용되는 대안은 다음과 같습니다.

1. ECMAScript의 Object.keys()

Object.keys(obj).length; 키를 내부적으로 반복하여 임시 배열을 계산하고 길이를 반환하는 방식으로 작동합니다.

  • 장점 - 읽기 쉽고 깔끔한 구문. 기본 지원을 사용할 수 없는 경우 shim을 제외하고 라이브러리 또는 사용자 지정 코드가 필요하지 않습니다.
  • 단점 - 어레이 생성으로 인한 메모리 오버헤드.

2. 라이브러리 기반 솔루션

이 항목의 다른 곳에 있는 많은 라이브러리 기반 예제는 해당 라이브러리의 컨텍스트에서 유용한 관용구입니다. Object.keys (네이티브 또는 shimmed)를 캡슐화하기 때문에 완벽한 라이브러리가 없는 코드와 비교할 때 얻을 수 있는 것은 없습니다.

3. for 루프 최적화

이러한 for 루프의 가장 느린 부분 은 일반적으로 함수 호출 오버헤드 때문에 .hasOwnProperty() 따라서 JSON 객체의 항목 수만 원할 때 Object.prototype 을 확장하거나 확장할 코드가 없다는 것을 알고 있으면 .hasOwnProperty() 호출을 건너뜁니다.

k 로컬 var k ) 접미사 대신 접두사 증가 연산자( ++count )를 사용하여 코드를 약간 최적화할 수 있습니다.

 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;

주어진 환경에서 이것이 더 빠른지 아닌지는 벤치마킹의 문제입니다. 어쨌든 매우 제한된 성능 향상을 기대할 수 있습니다.


Community Wiki

실제로 성능 문제가 발생하는 경우 적절하게 명명된(크기?) 속성을 증가/감소시키는 함수로 개체에 속성을 추가/제거하는 호출을 래핑하는 것이 좋습니다.

속성의 초기 수를 한 번만 계산하고 거기에서 계속 진행하면 됩니다. 실제 성능 문제가 없다면 신경쓰지 마십시오. getNumberOfProperties(object) 함수에서 해당 코드 비트를 래핑하고 작업을 완료하십시오.


Confusion

다음은 세 가지 방법에 대한 몇 가지 성능 테스트입니다.

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;

기본적으로 Map은 자체 크기를 추적하므로 숫자 필드만 반환합니다. 다른 어떤 방법보다 훨씬 빠릅니다. 개체를 제어할 수 있는 경우 대신 지도로 변환합니다.


Steve Cooper

Avi Flax에 의해 언급된 바와 같이,

 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 와 동일한 브라우저 지원을 제공합니다.

그러나 대부분의 경우 이러한 유형의 작업에 무수한 항목을 포함하고 싶지 않을 수 있지만 항상 차이점을 아는 것이 좋습니다. ;)


BenderTheOffender

이전 답변에서 답변한 대로: Object.keys(obj).length

하지만: 이제 ES6에 실제 Map 클래스가 있으므로 객체의 속성을 사용하는 대신 이 클래스를 사용하는 것이 좋습니다.

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

Flavien Volken

나는 이것을 할 방법을 모른다. 그러나 반복을 최소한으로 유지하려면 __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__ 함수가 실행되고 다시 계산됩니다.


Luke Bennett

Avi Flax의 답변 을 반복하려면 연결된 기능이 없는 객체에 대해 Object.keys(obj).length 가 맞습니다.

예시:

 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 사용하여 파일에 얼마나 많은 함수가 있는지 계산하려는 경우)

또한 예, 제 예제에서는 Node.js _ 또는 Underscore.js 모듈을 사용했습니다.

문서는 여기 에서 찾을 수 있을 뿐만 아니라 GitHub 및 기타 다양한 정보에서 소스를 찾을 수 있습니다.

그리고 마지막으로 lodash 구현 https://lodash.com/docs#size

_.size(obj)


Belldandu

프로젝트에 Underscore.js가 포함된 사용자는 다음을 수행할 수 있습니다.

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

또는 기능적 스타일:

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

hakunin

Object.defineProperty()에서 :

Object.defineProperty(obj, prop, 설명자)

다음 중 하나를 모든 개체에 추가할 수 있습니다.

 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..in 루프에 표시되지 않습니다.

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

산출:

 name: John Doe email: leaked@example.com

참고: Internet Explorer 9 이전의 브라우저에서는 작동하지 않습니다.


lepe

이 문제를 해결한 방법은 개체에 저장된 항목 수에 대한 기록을 유지하는 기본 목록을 직접 구현하는 것입니다. 매우 간단합니다. 이 같은:

 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]; } }

Ali

프로젝트에 Ext JS 4가 있는 경우 다음을 수행할 수 있습니다.

 Ext.Object.getSize(myobj);

이것의 장점은 모든 Ext JS 호환 브라우저( Internet Explorer 6 - Internet Explorer 8 포함)에서 작동한다는 것입니다. 그러나 다른 제안된 솔루션과 마찬가지로 실행 시간이 O(n)보다 좋지 않다고 생각합니다.


Mark Rhodes

당신이 사용할 수있는:

 Object.keys(objectName).length;

그리고

 Object.values(objectName).length;

Fayaz

OP는 개체가 nodeList인지 지정하지 않았습니다. 그렇다면 길이 방법을 직접 사용할 수 있습니다. 예시:

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

Robert Sinclair

이전 답변의 jQuery가 작동하지 않으면 시도하십시오.

 $(Object.Item).length

codejoecode

다음과 같이 모든 개체에서 사용할 수 있도록 하려고 합니다.

 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

Taquatech

나는 이것이 가능하다고 생각하지 않습니다 (적어도 일부 내부를 사용하지 않고는 아닙니다). 그리고 이것을 최적화하면 많은 것을 얻을 수 있다고 생각하지 않습니다.


amix

출처 : http:www.stackoverflow.com/questions/126100/how-to-efficiently-count-the-number-of-keys-properties-of-an-object-in-javascrip

반응형