كيفية بكفاءة الاعتماد على عدد من المفاتيح/خصائص كائن في جافا سكريبت ؟
-
02-07-2019 - |
سؤال
ما هي أسرع طريقة لحساب عدد من مفاتيح/خصائص كائن ؟ فإنه من الممكن أن تفعل هذا دون بالتكرار على الكائن ؟ أيدون أن تفعل
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(فايرفوكس لم توفر السحر __count__
مكان الإقامة ، ولكن هذا تم إزالتها في مكان ما حول الإصدار 4.)
المحلول
للقيام بذلك في أي ES5 المتوافقة مع البيئة, مثل عقدة, كروم, إنترنت إكسبلورر 9+, Firefox 4+ أو سفاري 5+:
Object.keys(obj).length
- التوافق المتصفح
- الكائن.مفاتيح الوثائق (يتضمن الطريقة التي يمكنك إضافتها إلى غير 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;
إذا كنت تستخدم Underscore.js يمكنك استخدام _.حجم (شكرا @douwe):
_.size(obj)
بدلا من ذلك يمكنك أيضا استخدام _.مفاتيح والتي قد تكون أكثر وضوحا لبعض:
_.keys(obj).length
أنا أوصي التأكيد ، ضيق مكتبة تفعل الكثير من الأشياء الأساسية.كلما كان ذلك ممكنا أنها مباراة ECMA5 و تؤجل تنفيذ الأصلي.
وإلا الدعم @Avi الجواب.وأنا تحريره لإضافة رابط MDC doc التي تشمل المفاتيح (طريقة) يمكنك إضافتها إلى غير ECMA5 المتصفحات.
مستوى تنفيذ الكائن (ES5.1 الكائن الداخلية الخصائص و الأساليب) لا يحتاج Object
لتعقب عدد من مفاتيح/خصائص ، لذلك يجب أن يكون هناك طريقة قياسية لتحديد حجم Object
دون صراحة أو ضمنا بالتكرار على مفاتيحها.
حتى هنا هي الأكثر استخداما البدائل:
1.ECMAScript هو كائن.مفاتيح()
Object.keys(obj).length;
يعمل عن طريق داخليا بالتكرار على مفاتيح حساب مؤقت مجموعة وإرجاع طوله.
- الايجابيات للقراءة و نظيفة الجملة.أي مكتبة أو العرف رمز المطلوبة ما عدا الرقائق إذا دعم أصلي غير متوفر
- سلبيات - الذاكرة العلوية بسبب إنشاء مجموعة.
2.مكتبة الحلول المستندة إلى
العديد من مكتبة يستند إلى أمثلة أخرى في هذا الموضوع مفيدة التعابير في سياق المكتبة.من وجهة نظر ، ومع ذلك ، لا يوجد شيء للحصول على مقارنة الكمال لا رمز المكتبة منذ كل تلك المكتبة أساليب فعلا لتغليف إما عن حلقة أو ES5 Object.keys
(الأم أو shimmed).
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;
إذا كان هذا هو أسرع أو لا على بيئة معينة هي مسألة القياس.محدودة جدا كسب الأداء يمكن أن يكون من المتوقع على أي حال.
إذا كنت تعمل في الواقع إلى مشكلة أداء أود أن أقترح التفاف المكالمات إضافة/إزالة خصائص/من وجوه مع وظيفة أيضا الزيادات/decrements مناسب اسمه (الحجم؟) مكان الإقامة.
تحتاج فقط إلى حساب العدد الأولي من خصائص مرة واحدة والانتقال من هناك.إذا لم يكن هناك الأداء الفعلي المشكلة, لا تهتم.مجرد التفاف قليلا من التعليمات البرمجية في الدالة getNumberOfProperties(object)
وينبغي القيام به معها.
أنا لست على علم بأي طريقة للقيام بذلك ، ومع ذلك للحفاظ على التكرار إلى الحد الأدنى ، قد تتمكن من محاولة التحقق من الوجود __count__
و إذا لم يكن موجودا (أي لا فايرفوكس) ثم هل يمكن أن يكرر أكثر من موضوع تحديد لاستخدامها لاحقا على سبيل المثال:
if (myobj.__count__ === undefined) {
myobj.__count__ = ...
}
هذه الطريقة أي دعم المتصفح __count__
استخدام هذا التكرار من شأنه أن تتم إلا عن تلك التي لا.إذا كان عدد التغييرات و لا يمكنك فعل هذا, أنت يمكن أن تجعل دائما وظيفة:
if (myobj.__count__ === undefined) {
myobj.__count__ = function() { return ... }
myobj.__count__.toString = function() { return this(); }
}
هذه الطريقة في أي وقت يمكنك الرجوع myobj.__count__
الدالة النار حساب.
كما ذكر من قبل Avi الكتان https://stackoverflow.com/a/4889658/1047014
Object.keys(obj).length
سوف تفعل خدعة لجميع خصائص enumerable على وجوه الخاص بك ولكن أيضا تشمل غير enumerable خصائص يمكنك بدلا من ذلك استخدام 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
ومع ذلك, في معظم الحالات, قد لا ترغب في تضمين nonenumerables في هذا النوع من العمليات ، ولكن من الجيد دائما أن تعرف الفرق ;)
تكرار على Avi الكتان الجواب من وجوه.مفاتيح(الكائنات).طول هو الصحيح لكائن التي لا يجب الوظائف المرتبطة به
على سبيل المثال:
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)
بالنسبة لأولئك الذين لديهم Underscore.js المدرجة في المشروع يمكنك القيام به:
_({a:'', b:''}).size() // => 2
أو نمط وظيفي:
_.size({a:'', b:''}) // => 2
من: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
الكائن.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);
ميزة هذا الوضع هو أنه سوف يعمل على كل تحويلة متوافق مع المتصفحات (IE6-IE8 شمل) ، ومع ذلك ، أعتقد أن الوقت يعمل ليس أفضل من O(n) على الرغم كما هو الحال مع غيرها من الحلول المقترحة.
يمكنك استخدام Object.keys(data).length
العثور على طول كائن JSON وجود البيانات الرئيسية
إذا مسج أعلاه لا يعمل, ثم حاول
$(Object.Item).length
المرجع لم تحدد إذا كان الكائن هو 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
جوجل إغلاق لطيفة وظيفة هذا...goog.الكائن.getCount(الكائنات)
يمكنك استخدام: Object.keys(objectName).length;
& Object.values(objectName).length;