[javascript] JavaScript에서 객체의 키 / 속성 수를 효율적으로 계산하는 방법은 무엇입니까?

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

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

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



답변

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

Object.keys(obj).length

답변

이 코드를 사용할 수 있습니다 :

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;


답변

당신이 사용하는 경우 Underscore.js를 당신이 사용할 수있는 _.size (감사 @douwe을) :
_.size(obj)

또는 _.keys 를 사용할 수도 있습니다.
_.keys(obj).length

많은 기본 작업을 수행하기위한 엄격한 라이브러리 인 Underscore를 강력히 권장합니다. 가능할 때마다 ECMA5와 일치하고 기본 구현을 연기합니다.

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


답변

표준 Object 구현 ( ES5.1 Object Internal Properties and Methods )에는 Object키 / 속성 수를 추적 할 필요가 없으므로 키 Object를 명시 적으로 또는 암시 적으로 반복하지 않고 크기를 결정하는 표준 방법이 없어야 합니다.

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

1. ECMAScript의 Object.keys ()

Object.keys(obj).length;의 작품 내부 의 키 반복 임시 배열을 계산하고 그 길이를 반환합니다.

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

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

이 주제의 다른 곳에서 많은 라이브러리 기반 예제는 라이브러리와 관련하여 유용한 관용구입니다. 그러나 성능 관점에서 볼 때 모든 라이브러리 메소드는 실제로 for-loop 또는 ES5 Object.keys(네이티브 또는 shimmed)를 캡슐화하므로 완벽한 라이브러리가없는 코드와 비교할 때 얻을 것이 없습니다 .

3. for-loop 최적화

이러한 for-loop 의 가장 느린 부분.hasOwnProperty()함수 호출 오버 헤드로 인해 일반적으로 호출입니다. 따라서 JSON 객체의 항목 수를 원할 때 .hasOwnProperty()코드가 없거나 확장되지 않는다는 것을 알고 있으면 호출을 건너 뜁니다 Object.prototype.

그렇지 않으면 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;

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


답변

실제로 성능 문제가 발생하는 경우 적절한 이름의 (크기?) 속성을 늘리거나 줄이는 함수를 사용하여 객체에 속성을 추가하거나 제거하는 호출을 래핑하는 것이 좋습니다.

초기 속성 수를 한 번만 계산하고 거기서부터 계속 진행하면됩니다. 실제 성능 문제가 없다면 귀찮게하지 마십시오. 함수에 그 코드를 감아 서 getNumberOfProperties(object)끝내십시오.


답변

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

그러나 대부분의 경우 이러한 유형의 작업에 숫자를 포함하지 않으려는 경우가 있지만 항상 차이점을 아는 것이 좋습니다.)


답변

나는 이것을 할 수있는 방법을 모른다. 그러나 반복을 최소화하기 위해 존재 여부를 확인하려고 시도하고 존재 __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__함수가 실행되고 다시 계산됩니다.