【问题标题】:Use pop() with JavaScript Associative Arrays将 pop() 与 JavaScript 关联数组一起使用
【发布时间】:2014-03-20 22:11:20
【问题描述】:

如何在 JS 中执行以下操作?我想在对象而不是数组上模仿.pop()。

var deck = { 
    'cardK' :'13',
    'cardQ' :'12',
    'cardAJ':'11'
};

var val = deck.pop();


console.log("Key" + val.key ); 
console.log("Value" + val.val ); 

好像不可能。

【问题讨论】:

    标签: javascript arrays object associative-array


    【解决方案1】:

    在使用这种可以被视为关联数组的结构时,您需要使用不同的技术。像 pop()、slice() 甚至 .length 之类的东西都不会像数字键控数组那样起作用。

    当需要快速搜索键/值对时,我使用字符串键控对象数组。

    这是我刚刚创建的一个 jsPef,它显示了您的数组结构的好处:

    http://jsperf.com/bmcgin-object-array-tests(请记住,随着阵列变大,性能会越来越高)

    还请记住,值可以是数字、字符串、数组、函数、对象等...

    【讨论】:

      【解决方案2】:

      我相信你知道,.pop 是一个原型Array 方法,所以你不能将它与 Javascript 对象一起使用。

      在数组上调用.pop 将从数组中删除last 元素。但是,对象没有“最后一个”键值对,因为它们的顺序永远无法保证。尽管如此,如果您不关心顺序,您可以实现一个类似.pop 的函数来与对象一起使用,但同样,它不会删除并返回最终的键值对。

      这样的事情应该可以解决问题:

      function pop(obj) {
        for (var key in obj) {
          var val = obj[key];
          delete obj[key];
          return {
              'key'   : key,
              'val'   : val,
          };
        };
      };
      

      结合你的代码:

      var val = pop(deck);
      console.log('key: ' + val.key);
      console.log('aa: ' + val.val);
      

      【讨论】:

      • F.J. 20 分钟前已经提供了similar answer。
      • @FelixKling 如果我认为我的回答不够深入,我会删除它。在我看来,这比answering with "it's not possible" and providing a workaround that requires a different data structure 更有价值。
      • 这不是很危险吗?我不认为这是安全的。虽然它在大多数情况下可能有效,但我认为您不能在这里假设 for-in 返回的第一项将是添加到数组中的最后一项。您可能想要实现一个“键控”堆栈,以便知道弹出是否正常工作。 Pop 应始终删除并为您提供添加到数组中的最后一项。用 int 索引时很容易,但键/hases 不是以这种方式完成的。
      【解决方案3】:

      正如其他答案所建议的,这里最好的解决方案可能是使用对象数组。但是,您也可以创建自己的 pop 函数,从对象中删除键,例如:

      function pop(obj) {
          var key = Object.keys(obj).pop();
          var result = {key: key, val: obj[key]};
          delete obj[key];
          return result;
      }
      
      var val = pop(deck);
      

      您可以向Object.prototype 添加一个类似的pop 函数,这样您就可以使用deck.pop(),但我强烈建议不要使用这种设计。

      【讨论】:

      • 为什么不推荐这些结构?在某些情况下,它们提供最高级别的性能,例如,当您需要知道 cardQ var x = deck['cardQ']; 的值时,比通过数组循环查找对象要快得多。
      • @BrianMcGinity 这通常是不好的做法,会破坏封装developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…。目前它只会破坏for ... in,因为除非您检查Object.hasOwnProperty.call(obj,key),否则将列出您的Object.prototype.addedStuff,并且有些人认为无论如何使用for ... in 是不好的(不检查hasOwnproperty),但它仍然会破坏封装。您正在更改内置原型的 JavaScript,它们不是您可以更改的。
      • @HMR,我说可以使用按字符串索引的对象数组,并且在许多情况下,它优于按数字索引的对象数组。我并不是要暗示重新定义原型 pop() 或任何原型是一个好主意。
      【解决方案4】:

      .pop 仅在阵列上可用。在 JavaScript 中,对象(本质上是关联数组)不像数组那样有序,因此没有 .pop 方法。

      你可以使用数组:

      var deck = [
          { key: 'cardK', val: 13 },
          { key: 'cardQ', val: 12 },
          { key: 'cardAJ', val: 11 },
      ];
      
      var val = deck.pop();
      console.log('key: ' + val.key);
      console.log('aa: ' + val.val);
      

      【讨论】:

        【解决方案5】:

        你是对的,这是不可能的。将对象视为映射或哈希表,而不是“关联数组”。属性没有顺序,因此.pop 之类的方法没有意义(当然,除非它会删除随机属性,例如 Python 的字典)。

        如果你想使用.pop 和val.key 和val.val,你必须创建一个对象数组来代替:

        var deck = [
          {key: 'cardK', val: '13'},
          {key: 'cardQ', val: '12'},
          {key: 'cardAJ', val: '11'}
        ];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-02-13
          • 1970-01-01
          • 2014-03-15
          • 2017-04-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-27
          相关资源
          最近更新 更多