JavaScript에서 객체의 키/속성 수를 효율적으로 계산하는 방법은 무엇입니까?
-
02-07-2019 - |
문제
객체의 키/속성 수를 계산하는 가장 빠른 방법은 무엇입니까? 물체를 반복하지 않고이 작업을 수행 할 수 있습니까? 즉,하지 않고
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox는 마법을 제공했습니다 __count__
속성이지만 이것은 버전 4 주위 어딘가에 제거되었습니다.)
해결책
이 작업을 수행합니다 ES5 호환 환경, 와 같은 마디, Chrome, IE 9+, Firefox 4+ 또는 Safari 5+ :
Object.keys(obj).length
- 브라우저 호환성
- Object.keys 문서 (비 ES5 브라우저에 추가 할 수있는 메소드 포함)
다른 팁
이 코드를 사용할 수 있습니다.
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;
사용중인 경우 aUNDSCORE.JS 당신이 사용할 수있는 _.크기 (감사합니다 @Douwe) :
_.size(obj)
또는 사용할 수도 있습니다 _.keys 일부는 더 명확 할 수 있습니다.
_.keys(obj).length
나는 많은 기본적인 일을하기위한 타이트한 라이브러리 인 밑줄을 강력히 추천합니다. 가능할 때마다 ECMA5와 일치하고 기본 구현을 연기합니다.
그렇지 않으면 나는 @avi의 답변을지지합니다. ECMA5 브라우저에 추가 할 수있는 Keys () 메소드가 포함 된 MDC DOC에 링크를 추가하기 위해 편집했습니다.
표준 객체 구현 (ES5.1 객체 내부 특성 및 방법)는 필요하지 않습니다 Object
키/속성 수를 추적하려면 Object
열쇠를 명시 적으로 또는 암시 적으로 반복하지 않고.
다음은 가장 일반적으로 사용되는 대안입니다.
1. ecmascript의 Object.keys ()
Object.keys(obj).length;
작품 내부적 키를 반복하여 임시 배열을 계산하고 길이를 반환합니다.
- 프로 - 읽기 쉽고 깨끗한 구문. 기본 지원을 사용할 수없는 경우 Shim을 제외하고는 라이브러리 또는 사용자 정의 코드가 필요하지 않습니다.
- 단점 - 배열 생성으로 인한 메모리 오버 헤드.
2. 라이브러리 기반 솔루션
이 주제의 다른 곳에서 많은 도서관 기반 예제는 라이브러리의 맥락에서 유용한 관용구입니다. 그러나 성능 관점에서, 모든 라이브러리 방법이 실제로 For-Loop 또는 ES5를 캡슐화하기 때문에 완벽한 비축 코드와 비교할 때 얻을 수있는 것은 없습니다. Object.keys
(기본 또는 반짝임).
3. 루프를 최적화합니다
그만큼 가장 느린 부분 그러한 루프의는 일반적으로입니다 .hasOwnProperty()
함수 호출 오버 헤드로 인해 호출. 그래서 JSON 객체의 항목 수를 원할 때 .hasOwnProperty()
코드가 연장되지 않았다는 것을 알고 있다면 전화하십시오. Object.prototype
.
그렇지 않으면 코드가 만들어서 매우 최적화 될 수 있습니다. k
현지의 (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;
주어진 환경에서 이것이 더 빠르든지 여부는 벤치마킹의 문제입니다. 어쨌든 매우 제한된 성능 이득이 예상 될 수 있습니다.
실제로 성능 문제에 빠지는 경우, 특성을 객체로/제거하는 호출을 객체로/제거하는 호출을 적절하게 명명 된 (크기?) 속성을 증가/감소시키는 호출을 마무리하는 것이 좋습니다.
초기 속성 수를 한 번만 계산하고 그곳에서 계속 이동하면됩니다. 실제 성능 문제가 없다면 귀찮게하지 마십시오. 함수에 해당 코드를 감싸십시오 getNumberOfProperties(object)
그리고 그것으로 끝났습니다.
나는 이것을하는 방법을 알지 못하지만 반복을 최소한으로 유지하기 위해 존재를 확인할 수 있습니다. __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__
이 기능은 발사 및 재 계산됩니다.
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
그러나 대부분의 경우 이러한 유형의 작업에 비수기를 포함시키고 싶지는 않지만 차이점을 아는 것이 항상 좋습니다.)
Avi Flax Answer 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);});}} */
이를 피하기위한 단계 :
키 수를 계산하려는 객체에 함수를 넣지 마십시오.
별도의 객체를 사용하거나 함수를 위해 특별히 새 개체를 만드십시오 (파일에 얼마나 많은 함수가 있는지 계산하려는 경우
Object.keys(obj).length
)
또한 예, 내 예에서 nodejs의 _ 또는 밑줄 모듈을 사용했습니다.
문서는 여기에서 찾을 수 있습니다 http://underscorejs.org/ Github 및 기타 다양한 정보의 출처뿐만 아니라
그리고 마지막으로 lodash 구현 https://lodash.com/docs#size
_.size(obj)
밑줄이있는 사람들은 프로젝트에 포함 된 사람들을 위해 다음을 수행 할 수 있습니다.
_({a:'', b:''}).size() // => 2
또는 기능적 스타일 :
_.size({a:'', b:''}) // => 2
에서: https://developer.mozilla.org/en/docs/web/javascript/reference/global_objects/object/defineproperty
Object.DefineProperty (OBJ, 소품, 설명 자)
모든 개체에 추가 할 수 있습니다.
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 브라우저에서는 작동하지 않습니다.
이 문제를 해결 한 방법은 객체에 얼마나 많은 항목이 저장되어 있는지에 대한 기록을 유지하는 기본 목록의 자체 구현을 구축하는 것입니다. 매우 간단합니다. 이 같은:
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];
}
}
프로젝트에 EXT JS 4가있는 사람들은 다음을 수행 할 수 있습니다.
Ext.Object.getSize(myobj);
이것의 장점은 모든 EXT 호환 브라우저 (IE6-IE8 포함)에서 작동한다는 것입니다. 그러나 다른 제안 된 솔루션과 마찬가지로 실행 시간이 O (N)보다 낫지 않다고 생각합니다.
당신이 사용할 수있는 Object.keys(data).length
키 데이터가있는 JSON 객체의 길이를 찾으려면
위의 jQuery가 작동하지 않으면 시도하십시오
$(Object.Item).length
OP는 객체가 Nodelist인지 지정하지 않았으며, 그렇다면 만 사용할 수 있습니다. 길이 직접 메소드. 예시:
buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen');
나는 이것이 불가능하다고 생각하지 않습니다 (적어도 일부 내부를 사용하지 않고는 아닙니다). 그리고 나는 당신이 이것을 최적화함으로써 많은 것을 얻을 것이라고 생각하지 않습니다.
나는 다음과 같은 모든 객체에 그것을 사용할 수 있도록 노력합니다.
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
Google Closure는 이것에 대한 좋은 기능을 가지고 있습니다 ... goog.object.getCount (OBJ)
당신이 사용할 수있는: Object.keys(objectName).length;
& Object.values(objectName).length;