javascript - معلم - مميزات الجافا سكريبت




طول كائن جافا سكريبت (20)

إذا كان لدي كائن JavaScript ، فقل

var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

هل هناك طريقة أفضل في الممارسة أو مقبولة للحصول على طول هذا الكائن؟


palmsey: في الإنصاف إلى البروتوكول الاختياري ، تشير مستندات جافا سكريبت بشكل صريح إلى استخدام متغيرات من نوع الكائن بهذه الطريقة باسم "صفائف الارتباط".

وفي الإنصاف لpalmsey كان صحيحا تماما ، فهي ليست صفائف الارتباطية ، انهم بالتأكيد أشياء :) - القيام بعمل صفيف النقابي. ولكن فيما يتعلق بالنقطة الأوسع يبدو أن لديك الحق في ذلك طبقًا للمادة التي وجدتها:

اعتبرت JavaScript "المصفوفات الوراثية" ضارة

ولكن وفقا لهذا كله ، أليس الجواب المقبول نفسه ممارسة سيئة؟

حدد دالة حجم النموذج () للكائن

إذا تمت إضافة أي شيء آخر إلى الكائن .prototype ، فحينئذٍ ستفشل الشفرة المقترحة:

<script type="text/javascript">
Object.prototype.size = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
Object.prototype.size2 = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>

لا أعتقد أن الإجابة يجب أن تكون الإجابة المقبولة حيث لا يمكن الوثوق بها إذا كان لديك أي كود آخر يعمل في نفس سياق التنفيذ. للقيام بذلك بطريقة قوية بالتأكيد سوف تحتاج إلى تحديد طريقة حجم داخل myArray والتحقق من نوع الأعضاء كما تتكرر من خلالهم.


خاصية

Object.defineProperty(Object.prototype, 'length', {
    get: function () {
        var size = 0, key;
        for (key in this)
            if (this.hasOwnProperty(key))
                size++;
        return size;
    }
});

استعمال

var o = {a: 1, b: 2, c: 3};
alert(o.length); // <-- 3
o['foo'] = 123;
alert(o.length); // <-- 4

إذا كنت بحاجة إلى بنية بيانات ارتباطية تعرض حجمها ، فاستخدم بشكل أفضل خريطة بدلاً من كائن.

var myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3

إذا كنت تستخدم AngularJS 1.x ، يمكنك القيام بأشياء بطريقة AngularJS من خلال إنشاء فلتر واستخدام الشفرة من أي من الأمثلة الأخرى مثل ما يلي:

// Count the elements in an object
app.filter('lengthOfObject', function() {
  return function( obj ) {
    var size = 0, key;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) size++;
    }
   return size;
 }
})

استعمال

في وحدة التحكم الخاصة بك:

$scope.filterResult = $filter('lengthOfObject')($scope.object)

أو في وجهة نظرك:

<any ng-expression="object | lengthOfObject"></any>

إذا كنت لا تهتم بدعم Internet Explorer 8 أو أقل ، فيمكنك بسهولة الحصول على عدد الخصائص في كائن من خلال تطبيق الخطوتين التاليتين:

  1. تشغيل developer.mozilla.org/en/docs/Web/JavaScript/Reference/… للحصول على صفيف يحتوي على أسماء فقط تلك الخصائص التي يمكن Object.getOwnPropertyNames() أو Object.getOwnPropertyNames() إذا كنت تريد أيضاً تضمين أسماء الخصائص التي لا يمكن عدها.
  2. الحصول على خاصية .length من هذا الصفيف.

إذا كنت بحاجة إلى القيام بذلك أكثر من مرة ، يمكنك لف هذا المنطق في إحدى الوظائف:

function size(obj, enumerablesOnly) {
    return enumerablesOnly === false ?
        Object.getOwnPropertyNames(obj).length :
        Object.keys(obj).length;
}

كيفية استخدام هذه الوظيفة تحديدًا:

var myObj = Object.create({}, {
    getFoo: {},
    setFoo: {}
});
myObj.Foo = 12;

var myArr = [1,2,5,4,8,15];

console.log(size(myObj));        // Output : 1
console.log(size(myObj, true));  // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr));        // Output : 6
console.log(size(myArr, true));  // Output : 6
console.log(size(myArr, false)); // Output : 7

انظر أيضا هذا Fiddle لعرض.


إليك الحل الأكثر عبر المتصفح.

هذا أفضل من الإجابة المقبولة لأنه يستخدم Object.keys الأصلي إذا كان موجوداً. وبالتالي ، فهو الأسرع لجميع المتصفحات الحديثة.

if (!Object.keys) {
    Object.keys = function (obj) {
        var arr = [],
            key;
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                arr.push(key);
            }
        }
        return arr;
    };
}

Object.keys(obj).length;

إن الإجابة الأكثر قوة (أي التي تعكس نية ما تحاول القيام به أثناء التسبب في أقل عدد من الأخطاء) هي:

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

// Get the size of an object
var size = Object.size(myArray);

هناك نوع من الاتفاقية في JavaScript والتي لا تضيف أشياء إلى Object.prototype ، لأنها يمكن أن تكسر التعدادات في المكتبات المختلفة. عادة ما تكون إضافة أساليب إلى كائن آمنة.

إليك تحديثًا اعتبارًا من عام 2016 وانتشار واسع النطاق لـ ES5 وما بعدها. بالنسبة إلى IE9 + وكافة المتصفحات الحديثة الأخرى التي تعمل بنظام ES5 + ، يمكنك استخدام Object.keys() بحيث يصبح الرمز أعلاه مجرد:

var size = Object.keys(myObj).length;

هذا ليس من الضروري تعديل أي نموذج أولي موجود منذ أن تم Object.keys() الآن.


استخدم شيئًا بسيطًا مثل:

Object.keys(obj).length

لا يجب أن يكون الأمر صعبًا ولا يتطلب وظيفة أخرى لإنجازها.


تحصل هذه الطريقة على جميع أسماء خصائص الكائنات في مصفوفة ، بحيث يمكنك الحصول على طول هذا الصفيف الذي يساوي طول مفاتيح الكائن.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2

في بعض الحالات ، يكون من الأفضل تخزين الحجم في متغير منفصل. خاصة ، إذا كنت تضيف إلى الصفيف بواسطة عنصر واحد في مكان واحد ويمكن بسهولة زيادة الحجم. من الواضح أنه سيعمل بشكل أسرع إذا كنت بحاجة إلى التحقق من الحجم في كثير من الأحيان.


فيما يلي نسخة من إجابة جيمس كوغلان في كتاب CoffeeScript لمن تخلوا عن جافا سكريبت مباشرة :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size

لست خبيرًا في جافا سكريبت ، ولكن يبدو أنك ستحتاج إلى تكرار العناصر وحسابها نظرًا لأن الكائن لا يحتوي على طريقة طولية:

var element_count = 0;
for (e in myArray) {  if (myArray.hasOwnProperty(e)) element_count++; }

palmsey: في الإنصاف إلى البروتوكول الاختياري ، تشير وثائق جافا سكريبت بشكل صريح إلى استخدام متغيرات نوع الكائن بهذه الطريقة باسم "صفائف الارتباط".


ما عليك سوى استخدام هذا للحصول على length :

Object.keys(myObject).length

ماذا عن شيء من هذا القبيل -

function keyValuePairs() {
    this.length = 0;
    function add(key, value) { this[key] = value; this.length++; }
    function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}

مثل معظم مشاكل جافا سكريبت ، هناك العديد من الحلول. يمكنك توسيع الكائن الذي يعمل بشكل أفضل أو أسوأ مثل قاموس اللغات الأخرى (+ مواطنين من الدرجة الأولى). لا شيء خطأ في ذلك ، ولكن هناك خيار آخر يتمثل في إنشاء كائن جديد يلبي احتياجاتك الخاصة.

function uberject(obj){
    this._count = 0;
    for(var param in obj){
        this[param] = obj[param];
        this._count++;
    }
}

uberject.prototype.getLength = function(){
    return this._count;
};

var foo = new uberject({bar:123,baz:456});
alert(foo.getLength());

هناك اختلاف في بعض ما سبق:

var objLength = function(obj){    
    var key,len=0;
    for(key in obj){
        len += Number( obj.hasOwnProperty(key) );
    }
    return len;
};

إنها طريقة أكثر أناقة إلى حد ما لدمج hasOwnProp.


يمكنك ببساطة استخدام Object.keys(obj).length على أي كائن للحصول على طوله. إرجاع Object.keys صفيف يحتوي على كافة مفاتيح الكائن (الخصائص) التي يمكن أن تأتي في متناول اليد للبحث عن طول هذا الكائن باستخدام طول الصفيف المطابق. يمكنك حتى كتابة وظيفة لهذا الغرض. دعونا نصبح مبدعين ونكتب أسلوبًا لها أيضًا (إلى جانب خاصية getter أكثر تناسقًا):

function objLength(obj)
{
  return Object.keys(obj).length;
}

console.log(objLength({a:1, b:"summit", c:"nonsense"}));

// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));

// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
   return Object.keys(this).length;
}
console.log(obj.getLength());

// You can also write it as a method, which is more efficient as done so above

Object.defineProperty(Object.prototype, "length", {get:function(){
    return Object.keys(this).length;
}});
console.log(obj.length);

// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()


يمكنك دائمًا إجراء Object.getOwnPropertyNames(myObject).length للحصول على النتيجة نفسها التي [].length للمصفوفة العادية.


تحديث : إذا كنت تستخدم Underscore.js (مستحسن ، خفيف الوزن!) ، فيمكنك القيام بذلك

_.size({one : 1, two : 2, three : 3});
=> 3

إذا لم يكن الأمر كذلك ، ولا تريد التلاعب بخصائص الكائن لأي سبب من الأسباب ، وتستخدم بالفعل jQuery ، فيمكن الوصول إلى المكون الإضافي على قدم المساواة:

$.assocArraySize = function(obj) {
    // http://.com/a/6700/11236
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

حل بسيط:

  var myObject = {};      // ... your object goes here.

  var length = 0;

  for (var property in myObject) {
    if (myObject.hasOwnProperty(property)){
      length += 1;
    }
  };

  console.log(length);    // logs 0 in my example.




javascript-objects