【问题标题】:How to iterate over an Object's specific keys in JavaScript?如何在 JavaScript 中迭代对象的特定键?
【发布时间】:2018-04-06 03:51:27
【问题描述】:

我有一个对象,我想遍历该对象的一些特定键。如何做到这一点?

考虑下面的 sn-p:

如何遍历 table1、table2 和 table3 键而不是所有键?

var table_object = {
  table1: "hello world",
  table1_name: "greetings_english.html",
  table2: "hola",
  table2_name: "greetings_spanish.html",
  table3: "Bonjour",
  table3_name: "greetings_french.html"
};

【问题讨论】:

  • for (var key in table_object)代替for (var key of ["table1", …])?
  • 可以,但是键将在事件发生时动态创建,并根据文件数量命名。
  • 那么也许你想存储文件的数量,并使用for (var i=1; i<=fileCount; i++) { var key = "table"+i; … }
  • 或者,如果您将tablestablenames 存储为两个单独的数组,可能会更容易。
  • 如果你想要 vanilla js,为什么要标记这个 jquery?

标签: javascript jquery iteration


【解决方案1】:

您可以过滤键,然后迭代其余的。

var table_object = { table1: "hello world", table1_name: "greetings_english.html", table2: "hola", table2_name: "greetings_spanish.html", table3: "Bonjour", table3_name: "greetings_french.html" };

Object
    .keys(table_object)
    .filter(function (k) { return !/_/.test(k); })
    .forEach(function (k) { console.log(table_object[k]); });

【讨论】:

  • /^table(\d+)$/ 将明确匹配 table 后跟一些数字。
  • @NinaScholz 不是前缀,它包含在 ^$ 中。
  • /^([a-zA-Z0-9$]+)$/,或/^([a-zA-Z$]+)(\d+)$/。或者您可以更改正则表达式或整个过滤器函数。
【解决方案2】:

你必须指定你必须遍历哪些键:

var table_object = {
  table1: "hello world",
  table1_name: "greetings_english.html",
  table2: "hola",
  table2_name: "greetings_spanish.html",
  table3: "Bonjour",
  table3_name: "greetings_french.html"
};

var keysToIterateThrough = ["table1", "table2", "table3"];
keysToIterateThrough.forEach(key => {
    var value = table_object[key];
    console.log(`key: ${key} => value: ${value}`);
})

【讨论】:

  • 是一个选项,但通过正则表达式过滤也是一个选项。
【解决方案3】:

您必须使用Object.keys 来找出所有对象键,然后应用filter 方法来过滤它们。

var table_object = {
  table1: "hello world",
  table1_name: "greetings_english.html",
  table2: "hola",
  table2_name: "greetings_spanish.html",
  table3: "Bonjour",
  table3_name: "greetings_french.html"
};
var keysToIterate = ["table1", "table2", "table3_name"];
let values=Object.keys(table_object)
                .filter(a=>keysToIterate.includes(a))
                .map(a=> table_object[a]);
console.log(values);

【讨论】:

  • keysToIterate.filter(a => a in table_object) 代替Object.keys(table_object).filter(a => keysToIterate.includes(a)) 不是更简单(而且可能更有效)吗?
  • @IlmariKaronen,不,因为keysToIterate 是我们需要的带有键的数组。他必须过滤对象的键。
  • @IlmariKaronen 是的,这可行。是否更有效取决于对象通常有多大以及keysToIterate 不属于对象的频率。
【解决方案4】:

可以试试

var keys = ['table1', 'table2', 'table3']
Object.keys(table_object).forEach(function(key) {
    if (keys.indexOf(key) != -1) {
        var table_value = table_object[key]
    }
})

【讨论】:

  • 你可以通过迭代keys来加速它。
【解决方案5】:

可能无法迭代有限的键,但您可以拥有一个要迭代的键数组。然后遍历该数组以从对象中获取相应的值

var objKeys = ['table1', 'table2', 'table3']

var table_object = {
  table1: "hello world",
  table1_name: "greetings_english.html",
  table2: "hola",
  table2_name: "greetings_spanish.html",
  table3: "Bonjour",
  table3_name: "greetings_french.html"
};

objKeys.forEach(function(item) {
  console.log(table_object[item])

})

【讨论】:

  • for ( var i = 0; i < objKeys.length; i ++ ) {} 几乎在所有浏览器及其每个版本中都受支持。
【解决方案6】:

我认为在这种情况下更好的方法是让你的对象像这样:

var table = {
    "hello world": "greetings_english.html",
    "hola": "greetings_spanish.html",
    "bonjour": "greetings_french.html"
};

for( var i in table ) {
    console.log( i );
    console.log( table[ i ] );
}

或者你可以创建两个数组:

var greetings = [
    "hello world",
    "hola",
    "bonjour"
];
var names = [
    "greetings_english.html",
    "greetings_spanish.html",
    "greetings_french.html"
];

for( var i = 0; i < greetings.length; i ++ ) {
    console.log( greetings[ i ] );
    console.log( names[ i ] );
}

你可以用这个方法做一张桌子

但无论如何你的问题:

var table = {
    table1: "hello world",
    table1_name: "greetings_english.html",
    table2: "hola",
    table2_name: "greetings_spanish.html",
    table3: "bonjour",
    table3_name: "greetings_french.html"
};

// Now there are three methods

console.log( "--- Method 1 ---" );
Object.keys( table )
      .filter( function( key ) {
          return /^table(\d+)$/.test( key );
      } )
      .forEach( function( key ) {
          console.log( key );
          console.log( table[ key ] );
          console.log( table[ key + "_name" ] );
      } );
      
console.log( "--- Method 2 ---" );
for ( var i in table ) {
    if ( /^table(\d+)$/.test( i ) ) {
        console.log( i );
        console.log( table[ i ] );
        console.log( table[ i + "_name" ] );
    }
}
      
console.log( "--- Method 3 ---" );
var keys = [
    "table1",
    "table2",
    "table3"
];
for ( var i = 0; i < keys.length; i ++ ) {
    console.log( keys[ i ] );
    console.log( table[ keys[ i ] ] );
    console.log( table[ keys[ i ] + "_name" ] );
}

方法2最好。

【讨论】:

    【解决方案7】:

    您不需要花哨的过滤器或正则表达式来完成如此简单的任务!忽略那些误导性的答案,开始使用 JavaScript 的全部功能!
    您应该在您的对象上使用Object.defineProperty() 方法,并将您不想遍历的所有属性设置为enumerable: false。通过这种方式,您还可以将命名约定与逻辑分离。让我告诉你:

    // Defining iterable properties. This ones will be returned
    // by Object.keys()
    
    var table_object = {
      table1: "hello world",
      table2: "hola",
      table3: "Bonjour",
      // It works even if you declare them in advance
      // table1_name: "greetings_english.html",
      // table2_name: "greetings_spanish.html",
      // table3_name: "greetings_french.html",
    };
    
    // Declaring the not iterable properties. They can still be
    // accessed, but they will not be iterated through
    
    Object.defineProperty(table_object, "table1_name", {
      // delete the next line if you have already declared it
      value: "greetings_english.html", 
      enumerable: false
    });
    
    Object.defineProperty(table_object, "table2_name", {
      // delete the next line if you have already declared it
      value: "greetings_spanish.html",
      enumerable: false
    });
    
    Object.defineProperty(table_object, "table3_name", {
      // delete the next line if you have already declared it
      value: "greetings_french.html",
      enumerable: false
    });
    
    // Iterating through the object using for ... in, which iterates
    // over the keys
    
    for (var key in table_object) {
      console.log(table_object[key]);
    }

    仍然可以使用Object.getOwnPropertyNames() 检索不可枚举的属性以及所有可枚举的属性。
    但是,如果您打算在不再需要过滤时实际使用第二种方法来遍历所有属性,我必须给您一些建议:

    • enumerable 可以设置回true,所以如果是一次性更改,我强烈建议恢复它。

    • 如果过滤经常来回切换,那么您应该检查两次对象的结构,因为可能有更适合您需要的选项(例如对象中的数组)。

    【讨论】:

    • 我想过,但它比过滤键慢得多。
    • 另外,如果你真的关心性能,为什么不使用loops over filter function?。当然,我并不是说这是最快的解决方案,但我认为这是语义上最正确的解决方案,而且最重要的是,冻结浏览器并没有那么慢;P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2019-02-03
    • 2014-12-23
    • 1970-01-01
    • 2018-02-02
    • 2012-01-13
    • 2013-03-07
    相关资源
    最近更新 更多