オブジェクトのキー/プロパティの数を数える最も速い方法は何ですか?オブジェクトを繰り返すことなくこれを行うことは可能ですか?つまり、せずに
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefoxは魔法の__count__
プロパティを提供しましたが、これはバージョン4のどこかで削除されました。)
オブジェクトのキー/プロパティの数を数える最も速い方法は何ですか?オブジェクトを繰り返すことなくこれを行うことは可能ですか?つまり、せずに
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;
(Object.prototype.hasOwnProperty.call(obj, k))
ですか?
hasOwnProperty
が必要です。オブジェクト自体に設定されたプロパティのみを返します。
obj.hasOwnProperty(k)
(私は実際に元の投稿でこれを行いましたが、後で更新しました)。はのプロトタイプのhasOwnProperty
一部であるため、すべてのオブジェクトで使用できますObject
が、まれにこのメソッドが削除またはオーバーライドされるため、予期しない結果が生じる可能性があります。それからそれを呼び出すことにより、Object.prototype
それは少しより堅牢になります。使用する理由は、プロトタイプではなくcall
メソッドを呼び出したいためですobj
。
使用している場合はUnderscore.jsを、あなたは使用することができます_.size(感謝@douweを):
_.size(obj)
別の方法として、_。keysを使用することもできます。
_.keys(obj).length
私はUnderscoreを強くお勧めします。これは、多くの基本的なことを行うためのタイトなライブラリです。それらは可能な限りECMA5に一致し、ネイティブの実装に従います。
それ以外の場合は、@ Aviの回答をサポートします。編集して、ECMA5以外のブラウザに追加できるkeys()メソッドを含むMDCドキュメントへのリンクを追加しました。
_.keys(obj).length
私にとって最も効果的に機能したのは、戻りオブジェクトが、プロパティのないプレーンな文字列になる場合があるためです。_.size(obj)
一方で私は、文字列の長さをバック与え_.keys(obj).length
戻り0
Object.keys
内部的に使用されます。また、アンダースコアは、定義されていないfor..in
場合、ループ内のすべてのキーを配列にコピーしますObject.keys
。
標準のオブジェクト実装(ES5.1オブジェクトの内部プロパティとメソッド)はObject
、キー/プロパティの数を追跡する必要がないため、キーObject
を明示的または暗黙的に反復せずにのサイズを決定する標準的な方法はありません。
したがって、最も一般的に使用される選択肢は次のとおりです。
Object.keys(obj).length;
作品内部のキーを反復処理は、一時的な配列を計算し、その長さを返します。
このトピックの他の場所にある多くのライブラリベースの例は、ライブラリのコンテキストで役立つイディオムです。ただし、パフォーマンスの観点から見ると、完全なライブラリなしのコードと比較して、これらのライブラリメソッドはすべてforループまたはES5 Object.keys
(ネイティブまたはシム)を実際にカプセル化しているため、何も得ることがありません。
このようなforループの最も遅い部分は.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;
これが特定の環境でより高速であるかどうかは、ベンチマークの問題です。とにかく非常に限られたパフォーマンスの向上が期待できます。
var k in myobj
パフォーマンスが向上するのですか?私の知る限り、JavaScriptで新しいスコープを宣言するのは関数だけです。インループはこのルールの例外ですか?
for (var k in myobj) hasOwn.call(myobj, k) && ++count;
つまり、ifステートメントを単純な&&?に置き換えます。
Object.getOwnPropertyNames(obj).length
; はるかに簡単です。
実際にパフォーマンスの問題が発生している場合は、オブジェクトにプロパティを追加/削除する呼び出しを、適切な名前の(サイズ?)プロパティを増減する関数でラップすることをお勧めします。
プロパティの初期数を一度計算するだけで、そこから先に進みます。実際のパフォーマンスの問題がない場合は、気にしないでください。そのコードを関数にラップして、それで終わりです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
ただし、ほとんどの場合、これらのタイプの操作にnonnumerableを含めたくない場合がありますが、違いを知っておくとよいでしょう;)
Object.getOwnPropertyNames
、あなたはここに一人
私はこれを行う方法を知りませんが、反復を最小限に抑えるために、存在を確認してみて、存在__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__
関数が実行され、再計算されます。
Object.prototype.__count__
のGecko 1.9.3で削除されている:whereswalden.com/2010/04/06/... 数 -property・オブ・オブジェクト・-削除されています/
Object.__count__
無くなりました、そしてまた良いriddance。
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);});}} */
これを回避する手順:
キーの数を数えたいオブジェクトに関数を置かないでください
別のオブジェクトを使用するか、関数専用の新しいオブジェクトを作成します(を使用してファイルにある関数の数を数えたい場合Object.keys(obj).length
)
また、はい、私の例ではnodejsの_またはアンダースコアモジュールを使用しました
ドキュメントは、http://underscorejs.org/のほか、github上のソースやその他のさまざまな情報にあります。
そして最後に、lodash実装https://lodash.com/docs#size
_.size(obj)
Array(obj).length
:それは動作しません。http://jsfiddle.net/Jhy8M/
false
、私はまだどのように上の任意のドキュメントを見つけていませんでしたけれどもvar obj = { a: true, b: true }
異なる場合がありvar obj = {}; obj.a = true; obj.b = true;
W3の異なる解釈/意味がある場合、または単にをChromeで採用されました。
以下は、3つの方法のパフォーマンステストです。
https://jsperf.com/get-the-number-of-keys-in-an-object
20,7351秒あたり操作
非常にシンプルで互換性があります。高速で実行されますが、新しいキーの配列が作成されるため、コストがかかります。
return Object.keys(objectToRead).length;
1秒あたり15,734回の操作
let size=0;
for(let k in objectToRead) {
size++
}
return size;
やや遅いが、メモリ使用量の近くではないため、モバイルまたは他の小型マシン向けに最適化したい場合はおそらく良い
1秒あたり953,839,338回の操作
return mapToRead.size;
基本的に、Mapは独自のサイズを追跡するため、数値フィールドを返すだけです。他のどの方法よりもはるかに高速です。オブジェクトを制御できる場合は、代わりにマップに変換してください。
送信元: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..inループでは表示されません。
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];
}
}
var i = basiclist.count
while(i--){...}
add
古いアイテムを置き換えるかどうか、またはremove
存在しないインデックスで呼び出されるかどうかをチェックするように。また、リストがundefined
有効なアイテム値である場合、リストに特定のインデックスがあるかどうかを確認することもできません。
OPは、オブジェクトがnodeListであるかどうかを指定しませんでした。その場合は、直接lengthメソッドを使用できます。例:
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)