如何循环或枚举JavaScript对象?

How do I loop through or enumerate a JavaScript object?

我有一个javascript对象,如下所示:

1
2
3
4
5
var p = {
   "p1":"value1",
   "p2":"value2",
   "p3":"value3"
};

现在我要循环遍历所有p元素(p1p2p3…)并获取它们的键和值。我该怎么做?

如果需要,我可以修改javascript对象。我的最终目标是循环使用一些键值对,如果可能,我希望避免使用eval


您可以使用其他人所示的for-in循环。但是,您还必须确保获得的键是对象的实际属性,并且不是来自原型。

这是一个片段:

1
2
3
4
5
6
7
8
9
10
11
var p = {
   "p1":"value1",
   "p2":"value2",
   "p3":"value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key +" ->" + p[key]);
    }
}


在ecmascript 5下,可以将Object.keys()Array.prototype.forEach()组合在一起:

1
2
3
4
5
var obj = { first:"John", last:"Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ecmascript 6增加了for...of

1
2
3
for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ecmascript 8添加了Object.entries(),避免了查找原始对象中的每个值:

1
2
3
Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

Object.keys()Object.entries()都以与for...in循环相同的顺序迭代属性,但忽略原型链。只迭代对象自己的可枚举属性。


必须使用for in循环

但是在使用这种循环时要非常小心,因为这将沿着原型链循环所有属性。

因此,在使用for in循环时,始终使用hasOwnProperty方法来确定迭代中的当前属性是否确实是您要检查的对象的属性:

1
2
3
4
5
6
7
for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}


如果我们不提到循环遍历对象的替代方法,这个问题就不完整。

如今,许多著名的javascript库提供了自己的方法来迭代集合,即在数组、对象和类似数组的对象上迭代。这些方法使用方便,完全兼容任何浏览器。

  • 如果使用jquery,可以使用jQuery.each()方法。它可用于在对象和数组上无缝迭代:

    1
    2
    3
    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  • 在underline.js中,您可以找到方法_.each(),该方法迭代一系列元素,依次生成一个提供的函数(注意迭代器函数中的参数顺序!):

    1
    2
    3
    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  • lo dash提供了几种迭代对象属性的方法。基本的_.forEach()(或者它的别名_.each())对于在对象和数组之间循环很有用,但是!)具有length属性的对象被视为数组,为了避免这种行为,建议使用_.forIn()_.forOwn()方法(这些方法也首先有value参数):

    1
    2
    3
    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });

    _.forIn()迭代对象本身和继承的可枚举属性,而_.forOwn()只迭代对象本身的属性(基本上检查hasOwnProperty函数)。对于简单的对象和对象文本,这些方法中的任何一个都可以正常工作。

  • 通常,所有描述的方法与任何提供的对象具有相同的行为。除了使用本机for..in循环通常比任何抽象(如jQuery.each()循环)都要快,这些方法更易于使用,需要的编码更少,并提供更好的错误处理。


    在ecmascript 5中,您在literal-Object.keys的迭代字段中有了新的方法。

    有关MDN的详细信息

    在当前版本的浏览器(Chrome30、IE10、FF25)中,我的选择是作为更快的解决方案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var keys = Object.keys(p),
        len = keys.length,
        i = 0,
        prop,
        value;
    while (i < len) {
        prop = keys[i];
        value = p[prop];
        i += 1;
    }

    您可以将此方法的性能与jspef.com上的不同实现进行比较:

    • 扩展实现
    • 对象键迭代
    • 对象文本迭代

    您可以在kangax的compat表上看到浏览器支持

    对于旧浏览器,您可以使用简单而完整的polyfill

    UPD:

    本问题中所有最流行的perfjs.info案例的性能比较:

    对象文本迭代


    您可以像这样迭代:

    1
    2
    3
    for (var key in p) {
      alert(p[key]);
    }

    请注意,key不会采用该属性的值,它只是一个索引值。


    前言:

    • 对象属性可以是自己的(属性在对象本身上)或继承的(不在对象本身上,在对象的原型上)。
    • 对象属性可以是可枚举的或不可枚举的。许多属性枚举/数组中都遗漏了不可枚举的属性。
    • 属性名可以是字符串或符号。名称为符号的属性被排除在许多属性枚举/数组中。

    在2018年,通过对象属性循环的选项有:

  • for-in[mdn,spec]&mdash;一种循环结构,循环遍历对象的可枚举属性的名称,包括继承的属性,这些属性的名称是字符串
  • Object.keys[mdn,spec]&mdash;一个函数,提供对象自己的可枚举属性(其名称为字符串)的名称数组。
  • Object.values[mdn,spec]&mdash;提供对象自己可枚举属性值数组的函数。
  • Object.entries[mdn,spec]&mdash;一个函数,提供对象自身可枚举属性的名称和值的数组。
  • Object.getOwnPropertyNames[mdn,spec]&mdash;一个函数,提供对象自己的属性(甚至是不可枚举的属性)的名称数组,这些属性的名称是字符串。
  • Object.getOwnPropertySymbols[mdn,spec]&mdash;一个函数,提供对象自身属性(甚至是不可枚举属性)的名称数组,这些属性的名称都是符号。
  • Reflect.ownKeys[mdn,spec]&mdash;一个函数,提供对象自身属性(甚至是不可枚举的属性)的名称数组,无论这些名称是字符串还是符号。
  • 如果您想要一个对象的所有属性,包括不可枚举的继承属性,您需要在原型链中的每个对象上使用一个循环和Object.getPrototypeOf〔mdn,spec〕,并使用Object.getOwnPropertyNamesObject.getOwnPropertySymbolsReflect.ownKeys(例如在这个答案的底部)。
  • 除了for-in以外,所有这些函数都会在数组上使用某种循环结构(forfor-offorEach等)。

    实例:

    for-in

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const name in o) {
        const value = o[name];
        console.log(`${name} = ${value}`);
    }

    Object.keys(使用for-of循环,但可以使用任何循环结构):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const name of Object.keys(o)) {
        const value = o[name];
        console.log(`${name} = ${value}`);
    }

    Object.values

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const value of Object.values(o)) {
        console.log(`${value}`);
    }

    Object.entries

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const [name, value] of Object.entries(o)) {
        console.log(`${name} = ${value}`);
    }

    Object.getOwnPropertyNames

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const name of Object.getOwnPropertyNames(o)) {
        const value = o[name];
        console.log(`${name} = ${value}`);
    }

    Object.getOwnPropertySymbols

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const name of Object.getOwnPropertySymbols(o)) {
        const value = o[name];
        console.log(`${String(name)} = ${value}`);
    }

    Reflect.ownKeys

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (const name of Reflect.ownKeys(o)) {
        const value = o[name];
        console.log(`${String(name)} = ${value}`);
    }

    所有属性,包括继承的不可枚举属性:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // A prototype object to inherit from, with a string-named property
    const p = {answer: 42};
    // The object we'll look at, which inherits from `p`
    const o = Object.create(p);
    // A string-named property
    o.question ="Life, the Universe, and Everything";
    // A symbol-named property
    o[Symbol("author")] ="Douglas Adams";
    for (let depth = 0, current = o; current; ++depth, current = Object.getPrototypeOf(current)) {
        for (const name of Reflect.ownKeys(current)) {
            const value = o[name];
            console.log(`[${depth}] ${String(name)} = ${String(value)}`);
        }
    }
    1
    2
    3
    .as-console-wrapper {
      max-height: 100% !important;
    }


    Since es2015 is getting more and more popular I am posting this answer which include usage of generator and iterator to smoothly iterate through [key, value] pairs. As it is possible in other languages for instance Ruby.

    Ok here is a code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const MyObject = {
      'a': 'Hello',
      'b': 'it\'s',
      'c': 'me',
      'd': 'you',
      'e': 'looking',
      'f': 'for',
      [Symbol.iterator]: function* () {
        for (const i of Object.keys(this)) {
          yield [i, this[i]];
        }
      }
    };

    for (const [k, v] of MyObject) {
      console.log(`Here is key ${k} and here is value ${v}`);
    }

    有关如何执行迭代器和生成器的所有信息,请参见开发人员Mozilla页面。

    希望它能帮助别人。

    编辑:

    ES2017将包括Object.entries,这将使在对象中迭代[key, value]对更加容易。目前已知,根据TS39阶段信息,它将成为标准的一部分。

    我认为是时候更新我的答案了,让它变得比现在更新鲜。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const MyObject = {
      'a': 'Hello',
      'b': 'it\'s',
      'c': 'me',
      'd': 'you',
      'e': 'looking',
      'f': 'for',
    };

    for (const [k, v] of Object.entries(MyObject)) {
      console.log(`Here is key ${k} and here is value ${v}`);
    }

    您可以在上找到有关用法的更多信息动态页面


    通过带有foreach()的原型,它应该跳过原型链属性:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Object.prototype.each = function(f) {
        var obj = this
        Object.keys(obj).forEach( function(key) {
            f( key , obj[key] )
        });
    }


    //print all keys and values
    var obj = {a:1,b:2,c:3}
    obj.each(function(key,value) { console.log(key +"" + value) });
    // a 1
    // b 2
    // c 3


    在查看了这里所有的答案之后,我自己的使用不需要hasownpropy,因为我的JSON对象是干净的;添加任何额外的javascript处理真的没有意义。这就是我所用的:

    1
    2
    3
    4
    5
    for (var key in p) {
        console.log(key + ' => ' + p[key]);
        // key is key
        // value is p[key]
    }


    1
    2
    3
    for(key in p) {
      alert( p[key] );
    }

    注意:您可以在数组上执行此操作,但也将遍历length和其他属性。


    有趣的是,人们在这些答案中都提到了Object.keys()for...of,但从未将它们结合起来:

    1
    2
    3
    var map = {well:'hello', there:'!'};
    for (let key of Object.keys(map))
        console.log(key + ':' + map[key]);

    You can't just for...ofan Objectbecause it's not an iterator,and for...indexor .forEach()ing the Object.keys()is丑陋/低效。
    我很高兴大多数人都不接受for...in(有或没有检查.hasOwnProperty()),因为这也有点混乱,所以除了我上面的答案,我在这里说…

    你可以让普通的对象关联迭代!直接使用花哨的for...of
    在Chrome和FF中工作的演示(我假设只有ES6)

    1
    2
    3
    4
    5
    6
    7
    8
    var ordinaryObject = {well:'hello', there:'!'};
    for (let pair of ordinaryObject)
        //key:value
        console.log(pair[0] + ':' + pair[1]);

    //or
    for (let [key, value] of ordinaryObject)
        console.log(key + ':' + value);

    只要你包括我下面的垫片:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //makes all objects iterable just like Maps!!! YAY
    //iterates over Object.keys() (which already ignores prototype chain for us)
    Object.prototype[Symbol.iterator] = function() {
        var keys = Object.keys(this)[Symbol.iterator]();
        var obj = this;
        var output;
        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    不需要创建一个真正的映射对象,它没有很好的语法结构。

    1
    2
    3
    var trueMap = new Map([['well', 'hello'], ['there', '!']]);
    for (let pair of trueMap)
        console.log(pair[0] + ':' + pair[1]);

    事实上,使用这个填充程序,如果您仍然想利用地图的其他功能(不需要全部填充),但仍然想使用整洁的对象符号,因为对象现在是不可更改的,您现在可以从中创建地图了!

    1
    2
    //shown in demo
    var realMap = new Map({well:'hello', there:'!'});

    对于那些不喜欢填隙,或者不喜欢和prototype打交道的人来说,可以随意在窗口上做这个函数,然后把它称为getObjIterator()之类的函数;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //no prototype manipulation
    function getObjIterator(obj) {
        //create a dummy object instead of adding functionality to all objects
        var iterator = new Object();

        //give it what the shim does but as its own local property
        iterator[Symbol.iterator] = function() {
            var keys = Object.keys(obj)[Symbol.iterator]();
            var output;

            return {next:function() {
                if (!(output = keys.next()).done)
                    output.value = [output.value, obj[output.value]];
                return output;
            }};
        };

        return iterator;
    }

    现在您可以将其称为普通函数,而不影响其他任何函数

    1
    var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

    1
    for (let pair of getObjIterator(ordinaryObject))

    这没有理由不起作用。

    欢迎来到未来。


    Object.keys(obj) : Array

    retrieves all string-valued keys of all enumerable own (non-inherited) properties.

    So it gives the same list of keys as you intend by testing each object key with hasOwnProperty. You don't need that extra test operation than and Object.keys( obj ).forEach(function( key ){}) is supposed to be faster. Let's prove it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    var uniqid = function(){
                var text ="",
                        i = 0,
                        possible ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                for( ; i < 32; i++ ) {
                        text += possible.charAt( Math.floor( Math.random() * possible.length ) );
                }
                return text;
            },
            CYCLES = 100000,
            obj = {},
            p1,
            p2,
            p3,
            key;

    // Populate object with random properties
    Array.apply( null, Array( CYCLES ) ).forEach(function(){
        obj[ uniqid() ] = new Date()
    });

    // Approach #1
    p1 = performance.now();
    Object.keys( obj ).forEach(function( key ){
        var waste = obj[ key ];
    });

    p2 = performance.now();
    console.log("Object.keys approach took" + (p2 - p1) +" milliseconds.");

    // Approach #2
    for( key in obj ) {
        if ( obj.hasOwnProperty( key ) ) {
            var waste = obj[ key ];
        }
    }

    p3 = performance.now();
    console.log("for...in/hasOwnProperty approach took" + (p3 - p2) +" milliseconds.");

    在我的火狐中,我有以下结果

    • object.keys方法耗时40.21101451665163毫秒。
    • 对于……In/HasOwnProperty方法,花费了98.26163508463651毫秒。

    在Chrome上,差异更大http://codepen.io/dsheiko/pen/jdrqxa

    PS2:在ES6(EcmaScript 2015)中,可以更好地迭代iterable对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let map = new Map().set('a', 1).set('b', 2);
    for (let pair of map) {
        console.log(pair);
    }

    // OR
    let map = new Map([
        [false, 'no'],
        [true,  'yes'],
    ]);
    map.forEach((value, key) => {
        console.log(key, value);
    });


    这里是另一个迭代对象的方法。

    1
    2
    3
    4
    5
    6
    7
    8
       var p = {
    "p1":"value1",
    "p2":"value2",
    "p3":"value3"
    };


    Object.keys(p).forEach(key => { console.log(key, p[key]) })


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var p = {
       "p1":"value1",
       "p2":"value2",
       "p3":"value3"
    };

    for (var key in p) {
        if (p.hasOwnProperty(key)) {
            console.log(key +" =" + p[key]);
        }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    <p>

      Output:
      p1 = values1
      p2 = values2
      p3 = values3

    </p>


    Object.keys()方法返回给定对象自己的可枚举属性的数组。在这里阅读更多信息

    1
    2
    3
    4
    5
    6
    7
    var p = {
       "p1":"value1",
       "p2":"value2",
       "p3":"value3"
    };

    Object.keys(p).map((key)=> console.log(key +"->" + p[key]))


    您可以向所有对象添加一个简单的foreach函数,这样您就可以自动循环任何对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Object.defineProperty(Object.prototype, 'forEach', {
        value: function (func) {
            for (var key in this) {
                if (!this.hasOwnProperty(key)) {
                    // skip loop if the property is from prototype
                    continue;
                }
                var value = this[key];
                func(key, value);
            }
        },
        enumerable: false
    });

    对于那些不喜欢的人来说…在"-方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Object.defineProperty(Object.prototype, 'forEach', {
        value: function (func) {
            var arr = Object.keys(this);
            for (var i = 0; i < arr.length; i++) {
                var key = arr[i];
                func(key, this[key]);
            }
        },
        enumerable: false
    });

    现在,您可以简单地调用:

    1
    2
    3
    4
    p.forEach (function(key, value){
        console.log ("Key:" + key);
        console.log ("Value:" + value);
    });

    如果不想与其他foreach方法发生冲突,可以使用唯一的名称命名它。


    Only JavaScript code without dependencies:

    1
    2
    3
    4
    5
    6
    7
    8
    var p = {"p1":"value1","p2":"value2","p3":"value3
    <hr><P>使用纯JavaScript时,循环可能非常有趣。似乎只有ECMA6(新的2015 JavaScript规范)控制了循环。不幸的是,在我写这篇文章的时候,浏览器和流行的集成开发环境(IDE)仍然在努力完全支持新的铃声和口哨。</P><P>乍一看,这里是一个javascript对象循环在ECMA6之前的样子:</P>[cc lang="
    javascript"]for (var key in object) {
      if (p.hasOwnProperty(key)) {
        var value = object[key];
        console.log(key); // This is the key;
        console.log(value); // This is the value;
      }
    }

    此外,我知道这超出了这个问题的范围,但在2011年,ecmascript 5.1仅为数组添加了forEach方法,这基本上创建了一种新的改进方法来循环数组,同时仍保留了不可辩驳的对象和冗长而混乱的for循环。但奇怪的是,这种新的forEach方法不支持break,这导致了其他各种问题。

    基本上在2011年,除了许多流行的库(jquery、underline等)决定重新实现之外,没有真正可靠的方法来循环JavaScript。

    截至2015年,我们现在有了更好的现成方法来循环(和中断)任何对象类型(包括数组和字符串)。下面是当建议成为主流时,javascript中的循环最终会变成什么样子:

    1
    2
    3
    4
    for (let [key, value] of Object.entries(object)) {
        console.log(key); // This is the key;
        console.log(value); // This is the value;
    }

    请注意,截至2016年6月18日,大多数浏览器都不支持上述代码。即使在Chrome中,您也需要启用这个特殊标志,以便它工作:chrome://flags/#enable-javascript-harmony

    在这成为新的标准之前,旧方法仍然可以使用,但是在流行的库中也有其他的选择,甚至对于那些不使用这些库的人来说,还有一些轻量级的选择。


    我会这样做,而不是在每个for ... in循环中检查obj.hasOwnerProperty

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var obj = {a : 1};
    for(var key in obj){
        //obj.hasOwnProperty(key) is not needed.
        console.log(key);
    }
    //then check if anybody has messed the native object. Put this code at the end of the page.
    for(var key in Object){
        throw new Error("Please don't extend the native object");
    }

    在ES6中,我们有一些已知的符号来公开一些以前的内部方法,您可以使用它来定义迭代器如何为该对象工作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var p = {
       "p1":"value1",
       "p2":"value2",
       "p3":"value3",
        *[Symbol.iterator]() {
            yield *Object.keys(this);
        }
    };

    [...p] //["p1","p2","p3"]

    这将产生与在ES6循环中使用for…相同的结果。

    1
    2
    3
    for(var key in p) {
        console.log(key);
    }

    但了解您现在使用ES6的能力是很重要的!


    如果还想迭代不可枚举的属性,可以使用Object.getOwnPropertyNames(obj)返回直接在给定对象上找到的所有属性(可枚举或不可枚举)的数组。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var obj = Object.create({}, {
      // non-enumerable property
      getFoo: {
        value: function() { return this.foo; },
        enumerable: false
      }
    });

    obj.foo = 1; // enumerable property

    Object.getOwnPropertyNames(obj).forEach(function (name) {
      document.write(name + ': ' + obj[name] + '<br/>');
    });


    考虑到ES6,我想添加我自己的一勺糖,并提供一种迭代对象属性的方法。

    因为纯JS对象不能在开箱即用的情况下进行迭代,所以我们不能使用for..of循环来迭代其内容。但是没有人能阻止我们使它变得不可理喻。

    让我们有一个book对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    let book = {
      title:"Amazing book",
      author:"Me",
      pages: 3
    }

    book[Symbol.iterator] = function(){

      let properties = Object.keys(this); // returns an array with property names
      let counter = 0;
      let isDone = false;

      let next = () => {
        if(counter >= properties.length){
          isDone = true;
        }
        return { done: isDone, value: this[properties[counter++]] }
      }

      return { next };
    }

    既然我们做到了,我们可以这样使用它:

    1
    2
    3
    4
    5
    6
    7
    for(let pValue of book){
      console.log(pValue);
    }
    ------------------------
    Amazing book
    Me
    3

    或者,如果您知道ES6生成器的功率,那么您当然可以缩短上面的代码。

    1
    2
    3
    4
    5
    6
    7
    8
    book[Symbol.iterator] = function *(){

      let properties = Object.keys(this);
      for (let p of properties){
        yield this[p];
      }

    }

    当然,您可以将这种行为应用于所有对象,使Objectprototype级别上是可访问的。

    1
    Object.prototype[Symbol.iterator] = function() {...}

    此外,符合ITerable协议的对象可以与新的ES2015功能扩展运算符一起使用,因此我们可以将对象属性值作为数组读取。

    1
    2
    3
    4
    let pValues = [...book];
    console.log(pValues);
    -------------------------
    ["Amazing book","Me", 3]

    或者您可以使用析构函数赋值:

    1
    2
    3
    4
    5
    6
    let [title, , pages] = book; // notice that we can just skip unnecessary values
    console.log(title);
    console.log(pages);
    ------------------
    Amazing book
    3

    您可以使用我上面提供的所有代码来检查jspodle。


    1
    2
    3
        var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions
    <div class="
    suo-content">[collapse title=""]<ul><li><wyn>json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"&zwnj;&#8203;value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key +" ->" + json[i][key]); } } }</wyn></li></ul>[/collapse]</div><p><center>[wp_ad_camp_5]</center></p><hr><P>如果任何人需要循环访问具有条件的ArrayObjects:</P><P>[cc lang="javascript"]var arrayObjects = [{"building":"A","status":"good
    <hr><P>在最新的ES脚本中,您可以这样做:</P>[cc lang="javascript"]Object.entries(p);

    since ES06 you can get the values of an object as array with

    1
    let arrValues = Object.values( yourObject) ;

    它返回对象值的数组,而不是从原型中提取值!!

    mdn docs对象.values())

    还有钥匙(在我面前回答)

    1
    let arrKeys   = Object.keys(yourObject);


    对象在实现.next()方法时成为迭代器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    const james = {
    name: 'James',
    height: `5'10"`,
    weight: 185,

    [Symbol.iterator]() {
    let properties = []
    for (let key of Object.keys(james)){
         properties.push(key);
     }

    index = 0;
    return {
            next: () => {
                let key = properties[index];
                let value = this[key];
                let done = index >= properties.length - 1 ;
                index++;
                return { key, value, done };
            }
        };
      }

    };


    const iterator = james[Symbol.iterator]();

    console.log(iterator.next().value); // '
    James'
    console.log(iterator.next().value); // `5'
    10`
    console.log(iterator.next().value); // 185

    如果只在属性上迭代,请使用上面的答案之一,但是如果要在包括函数在内的所有内容上迭代,则可能需要使用object.getownprotynames(obj)

    1
    2
    3
    for (let o of Object.getOwnPropertyNames(Math)) {
      console.log(o);
    }

    我有时使用它来快速测试具有简单输入和输出的对象上的所有函数。


    这是如何循环通过一个javascript对象并将数据放入一个表中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <body>

    function createTable(objectArray, fields, fieldTitles) {
      let body = document.getElementsByTagName('body')[0];
      let tbl = document.createElement('table');
      let thead = document.createElement('thead');
      let thr = document.createElement('tr');

      for (p in objectArray[0]){
        let th = document.createElement('th');
        th.appendChild(document.createTextNode(p));
        thr.appendChild(th);
       
      }
     
      thead.appendChild(thr);
      tbl.appendChild(thead);

      let tbdy = document.createElement('tbody');
      let tr = document.createElement('tr');
      objectArray.forEach((object) => {
        let n = 0;
        let tr = document.createElement('tr');
        for (p in objectArray[0]){
          var td = document.createElement('td');
          td.appendChild(document.createTextNode(object[p]));
          tr.appendChild(td);
          n++;
        };
        tbdy.appendChild(tr);    
      });
      tbl.appendChild(tbdy);
      body.appendChild(tbl)
      return tbl;
    }

    createTable([
                  {name: 'Banana', price: '3.04'}, // k[0]
                  {name: 'Orange', price: '2.56'},  // k[1]
                  {name: 'Apple', price: '1.45'}
               ])


    Object.entries()功能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var p = {
           "p1":"value1",
           "p2":"value2",
           "p3":"value3"
        };

    for (var i in Object.entries(p)){
        var key = Object.entries(p)[i][0];
        var value = Object.entries(p)[i][1];
        console.log('key['+i+']='+key+' '+'value['+i+']='+value);
    }


    我在使用角的时候也遇到了类似的问题,这里是我找到的解决方案。

    步骤1。获取所有对象键。使用object.keys。此方法返回给定对象自己的可枚举属性的数组。

    步骤2。创建空数组。这是所有属性将要存在的地方,因为新的ngfor循环将指向这个数组,所以我们必须捕获所有属性。步骤3。迭代抛出所有键,并将每个键推入您创建的数组中。这就是代码中的情况。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        // Evil response in a variable. Here are all my vehicles.
    let evilResponse = {
     "car" :
        {
          "color" :"red",
          "model" :"2013"
        },
      "motorcycle":
        {
          "color" :"red",
          "model" :"2016"
        },
      "bicycle":
        {
          "color" :"red",
          "model" :"2011"
        }
    }
    // Step 1. Get all the object keys.
    let evilResponseProps = Object.keys(evilResponse);
    // Step 2. Create an empty array.
    let goodResponse = [];
    // Step 3. Iterate throw all keys.
    for (prop of evilResponseProps) {
        goodResponse.push(evilResponseProps[prop]);
    }

    这是原始帖子的链接。https://medium.com/@papaponmx/looping-over-object-properties-with-ngfor-in-angular-869cd7b2dcc


    • 单层缩进
    • 单组括号
    • 最高的浏览器兼容性
    • 属性安全

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var p = {"p1":"value1","p2":"value2","p3":"value3
    <hr><P>自ES2015以来,您可以使用for of循环直接访问元素:</P>[cc lang="
    javascript"]// before ES2015
    for(var key of elements){
      console.log(elements[key]);
    }


    // ES2015
    for(let element of elements){
      console.log(element);
    }

    希望这能帮助别人。


    因为询问者的[最终目标是循环通过一些键值对],最后不要寻找循环。

    [cc lang="javascript"]var p ={"p1":"value1","p2":"value2","p3":"value3