【问题标题】:How do I loop through or enumerate a JavaScript object?如何循环或枚举 JavaScript 对象?
【发布时间】:2021-10-08 10:10:37
【问题描述】:

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

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

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

如有必要,我可以修改 JavaScript 对象。我的最终目标是遍历一些键值对,如果可能的话,我想避免使用eval

【问题讨论】:

    标签: javascript loops for-loop each


    【解决方案1】:

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

    这里是 sn-p:

    var p = {
        "p1": "value1",
        "p2": "value2",
        "p3": "value3"
    };
    
    for (var key in p) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }

    使用 Object.keys() 替代:

    var p = {
        0: "value1",
        "b": "value2",
        key: "value3"
    };
    
    for (var key of Object.keys(p)) {
        console.log(key + " -> " + p[key])
    }

    注意使用for-of 而不是for-in,如果不使用它将在命名属性上返回未定义,Object.keys() 确保仅使用对象自己的属性而不使用整个原型链属性

    使用新的Object.entries() 方法:

    注意: Internet Explorer 本身不支持此方法。您可以考虑为旧版浏览器使用 Polyfill。

    const p = {
        "p1": "value1",
        "p2": "value2",
        "p3": "value3"
    };
    
    for (let [key, value] of Object.entries(p)) {
      console.log(`${key}: ${value}`);
    }
    

    【讨论】:

    • 在 javascript 中,每个对象都有一堆具有元信息的内置键值对。当您遍历对象的所有键值对时,您也在遍历它们。 hasOwnPropery() 过滤掉这些。
    • 实际上,For...in 并没有被弃用。 For each...in 是。但我真的很喜欢archaeologists这个词……我得开始用它了。
    • 如何添加循环的值?谢谢
    • (for..in) 用于对象,(for.. of) 用于数组
    • 感谢您的简单回答。它节省了我的时间。
    【解决方案2】:

    在 ECMAScript 5 下,您可以组合 Object.keys()Array.prototype.forEach()

    var obj = { first: "John", last: "Doe" };
    
    Object.keys(obj).forEach(function(key) {
        console.log(key, obj[key]);
    });
    

    ECMAScript 6 增加了for...of:

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

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

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

    你可以结合for...of、解构和Object.entries

    for (const [key, value] of Object.entries(obj)) {
        console.log(key, value);
    }
    

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

    【讨论】:

    • 为什么标准没有提供Object.forEach(obj, function (value, key) {...})? :( 当然obj.forEach(function...) 会更短并补充Array.prototype.forEach,但这会冒着让对象定义自己的forEach 属性的风险。我想Object.keys 防止回调修改对象的键。
    【解决方案3】:

    您必须使用 for-in 循环

    但是在使用这种循环时要非常小心,因为这会循环原型链上的所有属性

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

    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
    }
    

    【讨论】:

    • 这比 levik 的解决方案要好,因为它允许主逻辑只有一个嵌套循环,而不是两个;使代码更易于阅读。虽然我会松开 continue 周围的括号;它们是多余的。
    • 我不会亲自删除{ },因为没有它们的if 会让人有点不清楚if 的一部分是什么,什么不是。但我想这只是一个意见问题:)
    • 是的,我更喜欢保留{ },主要是为了避免在以后需要在if 范围内添加一些内容时造成混淆。
    • 阅读我之前的评论,我意识到我没有使用正确的术语,因为我说的是“if scope”;但请记住,JavaScript 仅具有函数作用域。所以我真正的意思是“如果阻止”。
    • “很遗憾,hasOwnProperty 是一种方法,而不是运算符,因此在任何对象中,它都可以替换为不同的函数,甚至是不是函数的值”
    【解决方案4】:

    如果我们不提及循环对象的替代方法,问题将不完整。

    如今,许多知名的 JavaScript 库都提供了自己的方法来迭代集合,例如 arraysobjects类数组对象 .这些方法使用方便,完全兼容任何浏览器。

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

      $.each(obj, function(key, value) {
          console.log(key, value);
      });
      
    2. Underscore.js 中,您可以找到方法 _.each(),它遍历元素列表,将每个元素依次生成给提供的函数(注意 中的参数顺序iteratee 函数!):

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

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

      _.forIn() 迭代对象的拥有和继承 可枚举属性,而_.forOwn() 仅迭代对象的拥有 属性(基本上检查hasOwnProperty功能)。对于简单的对象和对象字面量,这些方法中的任何一个都可以正常工作。

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

    【讨论】:

    • 获取值:$.each(obj, function (key, value) { console.log(value.title); });
    • 下划线和jquery如何改变参数真有趣:)
    【解决方案5】:

    前言:

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

    在 2018 年,您可以选择循环遍历对象的属性(列表后面有一些示例):

    1. for-in [MDN, spec] — 一种循环结构,遍历对象的可枚举属性的名称,包括名称为字符串的继承属性
    2. Object.keys [MDN, spec] — 提供对象的自己的可枚举属性的名称数组的函数名称是字符串。
    3. Object.values [MDN, spec] — 提供对象自己的数组的函数,可枚举的属性。
    4. Object.entries [MDN, spec] — 提供对象的自己的的名称​​和值的数组的函数,enumerable 属性(数组中的每个条目都是一个[name, value] 数组)。
    5. Object.getOwnPropertyNames [MDN, spec] — 一个函数,提供一个对象的自己的属性(甚至是不可枚举的)的名称数组,其名称为字符串。
    6. Object.getOwnPropertySymbols [MDN, spec] — 一个函数,提供对象的自己的属性(甚至是不可枚举的属性)的名称数组,其名称为符号。
    7. Reflect.ownKeys [MDN, spec] — 提供对象自己的属性(甚至是不可枚举属性)的名称数组的函数,无论这些名称是字符串或符号。
    8. 如果你想要一个对象的所有属性,包括不可枚举的继承属性,你需要使用循环和Object.getPrototypeOf [MDN, spec] 并使用Object.getOwnPropertyNamesObject.getOwnPropertySymbolsReflect.ownKeys 在原型链中的每个对象上(示例在此答案的底部)。

    除了for-in 之外的所有这些,您将在数组上使用某种循环构造(forfor-offorEach 等)。

    例子:

    for-in:

    // 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 循环,但您可以使用任何循环结构)

    // 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:

    // 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:

    // 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:

    // 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:

    // 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:

    // 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}`);
    }

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

    // 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)}`);
        }
    }
    .as-console-wrapper {
      max-height: 100% !important;
    }

    【讨论】:

    • 很好地添加了可枚举/不可枚举的对象属性。
    【解决方案6】:

    你可以像这样迭代它:

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

    注意key 不会接受属性的值,它只是一个索引值。

    【讨论】:

    • 这是重复的,甚至不完全正确。您需要检查 hasOwnProperty 以使其正常工作
    • 我最初根据上述评论对此表示反对,直到我意识到这个答案是第一位的,因此不是“重复的”。它可能不完整,但在许多情况下都可以正常工作。
    【解决方案7】:

    在 ECMAScript 5 中,您在字面量的迭代字段中有新的方法 - Object.keys

    您可以在MDN 上查看更多信息

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

    var keys = Object.keys(p),
        len = keys.length,
        i = 0,
        prop,
        value;
    while (i < len) {
        prop = keys[i];
        value = p[prop];
        i += 1;
    }
    

    您可以在jsperf.com 上比较这种方法与不同实现的性能:

    您可以在 Kangax's compat table 上看到浏览器支持

    对于旧浏览器,您有 simplefull polyfill

    UPD:

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

    object literal iteration

    【讨论】:

    • 确实,我只是想发布这个方法。但你打败了我:(
    【解决方案8】:

    性能

    今天 2020.03.06 我在 MacOs High Sierra v10.13.6 上的 Chrome v80.0、Safari v13.0.5 和 Firefox 73.0.1 上执行所选解决方案的测试

    结论

    • 基于for-in (A,B) 的解决方案对于大小对象的所有浏览器来说都是快速(或最快)
    • 令人惊讶的是for-of (H) 解决方案在 chrome 上适用于大小物体的速度很快
    • 基于显式索引i (J,K) 的解决方案在所有浏览器上对小对象都非常快(对于 Firefox,对于大对象也很快,但在其他浏览器上速度中等)
    • 基于迭代器 (D,E) 的解决方案最慢,不推荐
    • 解决方案 C 对于大物体来说很慢,对于小物体来说是中慢

    详情

    进行了性能测试
    • 小对象 - 有 3 个字段 - 你可以在你的机器上执行测试 HERE
    • 'big' object - 有 1000 个字段 - 你可以在你的机器上执行测试 HERE

    下面 sn-ps 给出了使用的解决方案

    function A(obj,s='') {
    	for (let key in obj) if (obj.hasOwnProperty(key)) s+=key+'->'+obj[key] + ' ';
      return s;
    }
    
    function B(obj,s='') {
    	for (let key in obj) s+=key+'->'+obj[key] + ' ';
      return s;
    }
    
    function C(obj,s='') {
      const map = new Map(Object.entries(obj));
    	for (let [key,value] of map) s+=key+'->'+value + ' ';
      return s;
    }
    
    function D(obj,s='') {
      let o = { 
        ...obj,
        *[Symbol.iterator]() {
          for (const i of Object.keys(this)) yield [i, this[i]];    
        }
      }
      for (let [key,value] of o) s+=key+'->'+value + ' ';
      return s;
    }
    
    function E(obj,s='') {
      let o = { 
        ...obj,
        *[Symbol.iterator]() {yield *Object.keys(this)}
      }
      for (let key of o) s+=key+'->'+o[key] + ' ';
      return s;
    }
    
    function F(obj,s='') {
    	for (let key of Object.keys(obj)) s+=key+'->'+obj[key]+' ';
      return s;
    }
    
    function G(obj,s='') {
    	for (let [key, value] of Object.entries(obj)) s+=key+'->'+value+' ';
      return s;
    }
    
    function H(obj,s='') {
    	for (let key of Object.getOwnPropertyNames(obj)) s+=key+'->'+obj[key]+' ';
      return s;
    }
    
    function I(obj,s='') {
    	for (const key of Reflect.ownKeys(obj)) s+=key+'->'+obj[key]+' ';
      return s;
    }
    
    function J(obj,s='') {
      let keys = Object.keys(obj);
    	for(let i = 0; i < keys.length; i++){
        let key = keys[i];
        s+=key+'->'+obj[key]+' ';
      }
      return s;
    }
    
    function K(obj,s='') {
      var keys = Object.keys(obj), len = keys.length, i = 0;
      while (i < len) {
        let key = keys[i];
        s+=key+'->'+obj[key]+' ';
        i += 1;
      }
      return s;
    }
    
    function L(obj,s='') {
      Object.keys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );
      return s;
    }
    
    function M(obj,s='') {
      Object.entries(obj).forEach(([key, value]) => s+=key+'->'+value+' ');
      return s;
    }
    
    function N(obj,s='') {
      Object.getOwnPropertyNames(obj).forEach(key => s+=key+'->'+obj[key]+' ');
      return s;
    }
    
    function O(obj,s='') {
      Reflect.ownKeys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );
      return s;
    }
    
    
    
    // TEST
    
    var p = {
        "p1": "value1",
        "p2": "value2",
        "p3": "value3"
    };
    let log = (name,f) => console.log(`${name} ${f(p)}`)
    
    log('A',A);
    log('B',B);
    log('C',C);
    log('D',D);
    log('E',E);
    log('F',F);
    log('G',G);
    log('H',H);
    log('I',I);
    log('J',J);
    log('K',K);
    log('L',L);
    log('M',M);
    log('N',N);
    log('O',O);
    This snippet only presents choosen solutions

    这是 chrome 上小对象的结果

    【讨论】:

      【解决方案9】:

      由于 es2015 越来越受欢迎,我发布了这个答案,其中包括使用生成器和迭代器来平滑迭代 [key, value] 对。就像 Ruby 等其他语言一样。

      好的,这是一个代码:

      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阶段信息,现在知道它将成为标准的一部分。

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

      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}`);
      }

      您可以在 MDN页面

      【讨论】:

      • 这对我来说看起来完全多余/不需要。您会将它添加到系统中的每个对象中吗?我认为提供迭代器的目的是让您可以执行“for(const [k, v] of myObject)”。它只是看起来像额外的代码,提供的额外价值很少。
      【解决方案10】:
      for(key in p) {
        alert( p[key] );
      }
      

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

      【讨论】:

      • 当使用这样的 for 循环时,key 只会采用索引值,因此只会提醒 0、1、2 等...您需要访问 p[key] .
      • 这是JavaScript中最慢的数组迭代方法。你可以在你的电脑上查看这个 - Best way to iterate over Arrays in JavaScript
      • @Pencroff:问题在于问题不在于循环遍历数组... ;)
      • 这是我在stackoverflow上不理解的。理查德给出了正确的答案,他是第一个给出这个答案的人,但他没有得到任何+1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); } 在警报中弹出“p1”和“p2”,那有什么问题???
      • 我认为主要区别在于质量:其他答案不仅说明如何,还说明注意事项(例如原型)以及如何处理这些注意事项。恕我直言,其他答案比我的好:)。
      【解决方案11】:

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

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

      【讨论】:

      • JSON 对象是否干净无关紧要。如果在任何其他时间某些代码在Object.prototype 上设置了一个属性,那么它将被for..in 枚举。如果你确定你没有使用任何库,那么你不需要调用hasOwnProperty
      • Object.create(null)创建可以完全干净
      【解决方案12】:

      通过 prototypeforEach() 应该跳过 prototype 链 属性:

      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
      

      【讨论】:

      • 小心原型:obj = { print: 1, each: 2, word: 3 } 产生 TypeError: number is not a function。使用forEach 匹配类似的Array 函数可能会在一定程度上降低风险。
      【解决方案13】:

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

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

      您不能只使用for...ofObject,因为它不是迭代器,而for...index.forEach() 使用Object.keys() 是丑陋/低效的。
      我很高兴大多数人都避免使用for...in(无论是否检查.hasOwnProperty()),因为这也有点混乱,所以除了我上面的回答之外,我在这里说...


      你可以让普通的对象关联迭代!行为就像 Maps,直接使用花哨的 for...of
      DEMO 在 Chrome 和 FF 中工作(我假设仅 ES6)

      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);
      

      只要你在下面包含我的垫片:

      //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;
          }};
      };
      

      无需创建一个没有漂亮语法糖的真实 Map 对象。

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

      事实上,有了这个 shim,如果你仍然想利用 Map 的其他功能(而不是全部填充)但仍然想使用整洁的对象表示法,因为对象现在是可迭代的,你现在可以制作一个 Map从它!

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

      对于那些不喜欢 shim 或一般不喜欢 prototype 的人,请随意在 window 上创建该功能,然后将其称为 getObjIterator()

      //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;
      }
      

      现在你可以把它当成一个普通的函数来调用,其他的都不受影响

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

      for (let pair of getObjIterator(ordinaryObject))
      

      There's no reason why that wouldn't work.

      欢迎来到未来。

      【讨论】:

      • Caseinpoint。只要人们向下滚动并发现它有帮助,这就是最重要的。通常是我尝试做某事,不喜欢我在网上看到的东西,最终弄明白了,然后我回来分享。这很好,在谷歌搜索我完全忘记的东西之前,我实际上已经找到了自己的答案!
      • @HelpMeStackOverflowMyOnlyHope 就我个人而言,我不喜欢修改我自己没有定义的对象的原型。
      • @JanusTroelsen 您是否阅读了整个答案? For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
      • 请注意,此技术不适用于普通对象,但仍然有用。
      • 它确实适用于普通对象,这就是重点(以及像 ordinaryObject 这样的变量名,以强调魔法仍然适用于这些类型)。你检查过演示吗?什么不适合你,@noɥʇʎԀʎzɐɹƆ? (P.S. 你的 SE 头像是老板)
      【解决方案14】:

      您还可以使用 Object.keys() 并像下面这样遍历对象键来获取值:

      var p = {
          "p1": "value1",
          "p2": "value2",
          "p3": "value3"
      };
      
      Object.keys(p).forEach((key)=> {
       console.log(key +' -> '+ p[key]);
      });

      【讨论】:

      • 你节省了我的时间,谢谢
      • 很高兴知道:)
      【解决方案15】:

      var p = {
          "p1": "value1",
          "p2": "value2",
          "p3": "value3"
      };
      
      for (var key in p) {
          if (p.hasOwnProperty(key)) {
              console.log(key + " = " + p[key]);
          }
      }
      <p>
        Output:<br>
        p1 = values1<br>
        p2 = values2<br>
        p3 = values3
      </p>

      【讨论】:

        【解决方案16】:

        Object.keys(obj) : 数组

        检索所有可枚举的自有(非继承)属性的所有字符串值键。

        因此,通过使用 hasOwnProperty 测试每个对象键,它会提供与您想要的相同的键列表。你不需要额外的测试操作,Object.keys( obj ).forEach(function( key ){}) 应该更快。让我们证明一下:

        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.");

        在我的 Firefox 中,我有以下结果

        • Object.keys 方法耗时 40.21101451665163 毫秒。
        • for...in/hasOwnProperty 方法耗时 98.26163508463651 毫秒。

        PS。在 Chrome 上差异更大http://codepen.io/dsheiko/pen/JdrqXa

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

        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);
        });

        【讨论】:

        【解决方案17】:

        Object.keys() 上使用for-of

        喜欢:

        let object = {
          "key1": "value1",
          "key2": "value2",
          "key3": "value3"
        };
        
        for (let key of Object.keys(object)) {
          console.log(key + " : " + object[key])
        }

        【讨论】:

          【解决方案18】:

          在最新的 ES 脚本中,你可以这样做:

          let p = {foo: "bar"};
          for (let [key, value] of Object.entries(p)) {
            console.log(key, value);
          }

          【讨论】:

          • 单独工作,但如果此函数为每个条件返回一个值则不起作用
          【解决方案19】:

          只有没有依赖关系的 JavaScript 代码:

          var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
          keys = Object.keys(p);   // ["p1", "p2", "p3"]
          
          for(i = 0; i < keys.length; i++){
            console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
          }
          

          【讨论】:

            【解决方案20】:

            单行且可读性更强的代码可以..

            Object.entries(myObject).map(([key, value]) => console.log(key, value))
            

            【讨论】:

              【解决方案21】:

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

              var p = {
                  "p1": "value1",
                  "p2": "value2",
                  "p3": "value3"
              };
              
              Object.keys(p).map((key)=> console.log(key + "->" + p[key]))

              【讨论】:

                【解决方案22】:

                这是另一种遍历对象的方法。

                   var p = {
                "p1": "value1",
                "p2": "value2",
                "p3": "value3"
                };
                
                
                Object.keys(p).forEach(key => { console.log(key, p[key]) })

                【讨论】:

                • 这很酷,但是对于大型对象,for 方法可能更高效。
                【解决方案23】:

                在javascript中迭代对象的多种方式

                使用 for...in 循环

                 var p = {
                    "p1": "value1",
                    "p2": "value2",
                    "p3": "value3"
                };
                for (let key in p){
                   if(p.hasOwnProperty(key)){
                     console.log(`${key} : ${p[key]}`)
                   }
                }

                使用 for...of 循环

                 var p = {
                    "p1": "value1",
                    "p2": "value2",
                    "p3": "value3"
                };
                for (let key of Object.keys(p)){
                     console.log(`key: ${key} & value: ${p[key]}`)
                }

                forEach()Object.keysObject.valuesObject.entries

                一起使用

                var p = {
                    "p1": "value1",
                    "p2": "value2",
                    "p3": "value3"
                };
                Object.keys(p).forEach(key=>{
                   console.log(`${key} : ${p[key]}`);
                });
                Object.values(p).forEach(value=>{
                   console.log(value);
                });
                Object.entries(p).forEach(([key,value])=>{
                    console.log(`${key}:${value}`)
                })

                【讨论】:

                  【解决方案24】:

                  使用纯 JavaScript 时,循环会非常有趣。似乎只有 ECMA6(新的 2015 JavaScript 规范)才能控制循环。不幸的是,在我写这篇文章时,浏览器和流行的集成开发环境 (IDE) 仍在努力完全支持新的花里胡哨。

                  以下是 ECMA6 之前的 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、Underscore 等)决定重新实现之外,没有一种真正可靠的 JavaScript 循环方式。

                  截至 2015 年,我们现在有了更好的开箱即用方式来循环(和中断)任何对象类型(包括数组和字符串)。当推荐成为主流时,JavaScript 中的循环最终会是这样的:

                  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

                  在这成为新标准之前,旧方法仍然可以使用,但在流行的库中也有替代方法,甚至lightweight alternatives 用于那些不使用任何这些库的人。

                  【讨论】:

                  • 你能提供这个工作的小提琴吗?这是我的尝试。 jsfiddle.net/abalter/sceeb211
                  • @abalter 抱歉,我意识到我的代码中有错字。我修复了它并在这里更新了你的 JsFiddle:jsfiddle.net/sceeb211/2
                  • 我正在使用 chrome 并收到 Uncaught TypeError: Object.entries is not a function。是不是还没有在 chrome 中实现?
                  • @abalter 是的。确保您拥有 Chrome 版本 51,并且您已按照我的编辑和 Jsfiddle cmets 中的说明启用了该标志。您可以在这里查看详细信息:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
                  • 抱歉,我错过了关于国旗的内容。我发现它还没有完全实现。
                  【解决方案25】:

                  你可以给所有对象添加一个简单的forEach函数,这样你就可以自动循环遍历任何对象:

                  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
                  });
                  

                  对于那些不喜欢“for ... in”方法的人:

                  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
                  });
                  

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

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

                  如果您不想与其他 forEach-Methods 发生冲突,您可以使用您的唯一名称命名它。

                  【讨论】:

                  • 修改内置对象的原型(如Object)通常被认为是一种反模式,因为它很容易与其他代码发生冲突。所以伤口建议这样做。
                  【解决方案26】:

                  在可枚举的 JavaScript 对象上循环的一个好方法是使用 Object.keysObject.entriesmap 函数。如下:

                  // assume items:
                  
                  const items = {
                    first: { name: 'phone', price: 400 },
                    second: { name: 'tv', price: 300 },
                    third: { name: 'sofa', price: 250 },
                  };
                  

                  对于循环并在ReactJS 上显示一些 UI,如下所示:

                  ~~~
                  <div>
                    {Object.entries(items).map(([key, ({ name, price })]) => (
                      <div key={key}>
                       <span>name: {name}</span>
                       <span>price: {price}</span>
                      </div>
                    ))}
                  </div>
                  

                  实际上,我使用了两次解构赋值,一次用于获取key,一次用于获取nameprice

                  【讨论】:

                  • 我正在寻找这个,因为我正在使用 React 以及 for 循环如何在 &lt;Fragment&gt; 中不起作用,这是完美的解决方案。非常感谢
                  • 亲爱的@Mob_Abominator,感谢您的甜言蜜语,我很高兴听到它对您有用。但我不明白how for loops don't work inside &lt;Fragment&gt;。它仍然有任何问题吗?如果确实如此,请留下问题并告诉我,我会回答。如果什么都没有,你现在没事了。请给this post of me点赞。谢谢。
                  【解决方案27】:

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

                  var p = {
                      "p1": "value1",
                      "p2": "value2",
                      "p3": "value3",
                      *[Symbol.iterator]() {
                          yield *Object.keys(this);
                      }
                  };
                  
                  [...p] //["p1", "p2", "p3"]
                  

                  这将得到与在 es6 循环中使用 for... 相同的结果。

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

                  但是了解你现在使用 es6 的能力很重要!

                  【讨论】:

                  • 自定义对象迭代器调用由Object.keys()生成并分配在内存中的数组的内置数组迭代器......酷!
                  【解决方案28】:

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

                  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");
                  }
                  

                  【讨论】:

                    【解决方案29】:

                    从 ES06 开始,您可以使用数组获取对象的值

                    let arrValues = Object.values( yourObject) ;
                    

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

                    MDN DOCS Object.values()

                    和钥匙(在这里我已经回答过了)

                    let arrKeys   = Object.keys(yourObject);
                    

                    【讨论】:

                    • 答案要求提供同时返回键和值的解决方案。
                    【解决方案30】:

                        var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
                    {"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
                    for(var value in p) {
                        for (var key in value) {
                            if (p.hasOwnProperty(key)) {
                                console.log(key + " -> " + p[key]);
                            }
                        }
                    }

                    【讨论】:

                    • json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i &lt; json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -&gt; " + json[i][key]); } } }
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多