代码之家  ›  专栏  ›  技术社区  ›  mjs

如何有效地计算javascript中对象的键/属性的数量?

  •  1301
  • mjs  · 技术社区  · 16 年前

    计算对象的键/属性数量的最快方法是什么?是否可以在不遍历对象的情况下执行此操作?也就是说,不做

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

    (火狐确实提供了一种魔力 __count__ 属性,但在版本4附近的某个位置删除了此属性。)

    20 回复  |  直到 5 年前
        1
  •  2157
  •   Zearin lifeisstillgood    10 年前

    在任何ES5兼容环境中执行此操作,例如 Node ,Chrome,IE 9+,FF 4+,或Safari 5+:

    Object.keys(obj).length
    
        2
  •  146
  •   Renaat De Muynck    6 年前

    您可以使用此代码:

    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;
    
        3
  •  132
  •   Sasha Chedygov    7 年前

    如果您正在使用 Underscore.js 你可以使用 _.size (谢谢@douwe):
    _.size(obj)

    或者您也可以使用 _.keys 这对一些人来说可能更清楚:
    _.keys(obj).length

    我强烈推荐使用下划线,它是一个用于执行许多基本操作的紧密库。只要可能,它们就会匹配ECMA5并遵从本机实现。

    否则我支持@avi的答案。我编辑了它以添加到MDC文档的链接,其中包括可以添加到非ECMA5浏览器的keys()方法。

        4
  •  68
  •   community wiki 6 revs, 3 users 90% Luc125    6 年前

    标准对象实现( ES5.1 Object Internal Properties and Methods )不需要 Object 跟踪其键/属性的数量,因此不应该有标准的方法来确定 对象 没有显式或隐式迭代其键。

    因此,以下是最常用的替代方案:

    1。ecmascript的object.keys()。

    Object.keys(obj).length; 作品 内部的 遍历键以计算临时数组并返回其长度。

    • 赞成的意见 -清晰易读的语法。如果本机支持不可用,则不需要库或自定义代码,只需要填充程序
    • 欺骗 -由于创建数组而导致的内存开销。

    2。基于库的解决方案

    本主题其他地方的许多基于库的示例都是在其库上下文中有用的习语。但是,从性能的角度来看,与完美的无库代码相比,没有什么可获得的,因为所有这些库方法实际上都封装了for循环或es5 Object.keys (原生或微光)。

    三。优化for循环

    这个 最慢部分 对于这样的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;
    

    在给定的环境中,这是否更快是一个基准测试问题。无论如何,预期的性能增益非常有限。

        5
  •  23
  •   hitautodestruct    11 年前

    如果您实际遇到性能问题,我建议使用一个函数来包装向对象添加/从对象中删除属性的调用,该函数还可以增加/减少一个适当命名的(大小?)。财产。

    您只需要计算一次初始属性数量,然后从那里继续。如果没有实际的性能问题,就不用麻烦了。只需将这段代码包装在一个函数中 getNumberOfProperties(object) 完成它。

        6
  •  15
  •   Luke Bennett    16 年前

    我不知道有什么方法可以做到这一点,但是为了将迭代次数保持在最小,您可以尝试检查 __count__ 如果它不存在(即不是火狐),那么您可以迭代该对象并定义它以供以后使用,例如:

    if (myobj.__count__ === undefined) {
      myobj.__count__ = ...
    }
    

    这样任何浏览器都支持 γ-γ 将使用它,并且迭代将只对那些不使用它的对象执行。如果计数发生变化,而您不能这样做,则可以始终使其成为一个函数:

    if (myobj.__count__ === undefined) {
      myobj.__count__ = function() { return ... }
      myobj.__count__.toString = function() { return this(); }
    }
    

    任何时候只要你提到MYOBJ。 γ-γ 函数将启动并重新计算。

        7
  •  15
  •   Community Mofi    7 年前

    如阿维亚麻所述 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
    

    如上所述 here 这与浏览器支持相同 Object.keys

    但是,在大多数情况下,您可能不希望在这些类型的操作中包含非数字项,但了解它们之间的区别总是很好的;)

        8
  •  12
  •   Belldandu    9 年前

    迭代avi-flax-answer-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);});}} */
    

    避免这种情况的步骤:

    1. 不要将函数放入要计算键数的对象中

    2. 使用单独的对象或为函数专门创建一个新对象(如果要计算文件中有多少函数,请使用 Object.keys(obj).length )

    同样,我在示例中使用了nodejs中的\或下划线模块

    文档可在此处找到 http://underscorejs.org/ 以及它在Github上的来源和各种其他信息

    最后是一个lodash实现 https://lodash.com/docs#size

    _.size(obj)

        9
  •  8
  •   hakunin    13 年前

    对于项目中包含underline.js的用户,可以执行以下操作:

    _({a:'', b:''}).size() // => 2
    

    或功能风格:

    _.size({a:'', b:''}) // => 2
    
        10
  •  6
  •   lepe    9 年前

    来自: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

    对象.定义属性(对象,属性,描述符)

    您可以将其添加到所有对象中:

    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浏览器。

        11
  •  5
  •   Ali    10 年前

    我解决这个问题的方法是建立我自己的基本列表实现,它记录对象中存储了多少项。很简单。像这样:

    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];
       }
    }
    
        12
  •  4
  •   Flavien Volken    6 年前

    如上所述: Object.keys(obj).length

    但是:我们现在有了一个真正的 Map 上ES6课,我会的 suggest 使用它而不是使用对象的属性。

    const map = new Map();
    map.set("key", "value");
    map.size; // THE fastest way
    
        13
  •  3
  •   Mark Rhodes    12 年前

    对于项目中有ExtJS4的用户,可以执行以下操作:

    Ext.Object.getSize(myobj);
    

    这样做的好处是,它可以在所有与ext兼容的浏览器(包括ie6-ie8)上工作,但是,我相信运行时间并不比o(n)好,就像其他建议的解决方案一样。

        14
  •  1
  •   Anuj Balan    12 年前

    如果上面的jquery不起作用,请尝试

    $(Object.Item).length
    
        15
  •  0
  •   amix    16 年前

    我认为这是不可能的(至少在没有使用内部结构的情况下是不可能的)。我不认为通过优化这一点你会得到很多。

        16
  •  0
  •   Taquatech    6 年前

    我试图使它对所有这样的对象都可用:

    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
    
        17
  •  0
  •   Codemaker2015    6 年前

    你可以使用 Object.keys(data).length 查找具有键数据的JSON对象的长度

        18
  •  0
  •   Sterling Diaz    5 年前

    您还可以使用

    JSON.parse(array).lenght
    
        19
  •  -1
  •   Sebastian Perez    13 年前

    谷歌关闭有一个很好的功能…goog.object.getcount(对象)

    look at goog.Object Documentation

        20
  •  -1
  •   Fayaz    6 年前

    你可以使用: Object.keys(objectName).length; & Object.values(objectName).length;