使用JavaScript关联数组时,可以使用pop()函数。

13

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

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

var val = deck.pop();


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

看起来似乎不可能。

5个回答

17

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

4

正如其他答案所建议的那样,这里最好的解决方案可能是使用对象数组。但是,您也可以创建自己的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'];比循环数组并查找对象要快得多。 - Brian McGinity
@BrianMcGinity 这是一种不好的编程实践,会破坏封装性 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain#Bad_practice.3A_Extension_of_native_prototypes。目前它只会破坏 for ... in,因为你的 Object.prototype.addedStuff 会被列出,除非你检查 Object.hasOwnProperty.call(obj,key),有些人认为使用 for ... in 本来就不好(没有检查 hasOwnproperty),但它仍然会破坏封装性。你正在更改 JavaScript 内置的原型,它们不属于你自己去更改。 - HMR
1
@HMR,我想说使用由字符串索引的对象数组是可以接受的,而且在许多情况下,它比由数字索引的对象数组更好。 我并不是要暗示重新定义pop()或任何原型是一个好主意。 - Brian McGinity

3
您说得对,这是不可能的。将对象视为“映射”或“哈希表”,而不是“关联数组”。属性没有顺序,因此像.pop这样的方法是没有意义的(除非它会删除一个随机属性,就像Python的字典一样)。
如果您想使用.popval.keyval.val,则必须创建一个对象数组:
var deck = [
  {key: 'cardK', val: '13'},
  {key: 'cardQ', val: '12'},
  {key: 'cardAJ', val: '11'}
];

1
正如您所知,.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分钟前已经提供了一个类似的答案。链接 - Felix Kling
@FelixKling 如果我不认为我的回答更加深入,我就会删除它。在我看来,这比[回答“不可能”并提供需要不同数据结构的解决方法](https://dev59.com/smEh5IYBdhLWcg3w5243#21899878)更有价值。 - Walter Roman
这不会很危险吗?我认为这不安全。虽然在大多数情况下可能有效,但我认为你不能假设for-in返回的第一项将是添加到数组中的最后一项。您可能希望实现一个“键控”堆栈,以便您知道pop是否正常工作。Pop应始终删除并提供添加到数组中的最后一项。当用int索引时很容易,但是键/哈希不是这样完成的。 - Quadrivium

1
当使用这种可以被视为关联数组的结构时,需要使用不同的技巧。像pop(),slice()甚至.length这样的东西在数字键数组中不起作用。
当需要快速搜索键/值对时,我使用字符串键对象数组。
这是我刚刚创建的jsPef,它展示了你的数组结构的好处: http://jsperf.com/bmcgin-object-array-tests(请记住,随着数组变得越来越大,性能会显著提高)
还要记住,值可以是数字、字符串、数组、函数、对象等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接