每个对象都是独立的吗?

127

我有一个 JavaScript 对象:

var object = someobject;

Object { aaa=true, bbb=true, ccc=true }

我如何在这种情况下使用each?

 object.each(function(index, value)) {
      console.log(value);
 }

不起作用。


https://dev59.com/pXNA5IYBdhLWcg3wh-cC - Phil Cross
你正在使用jQuery吗?你期望什么结果?控制台中会输出三个“true”吗? - davids
jQuery的$.each文档(http://api.jquery.com/jQuery.each/)有一个完美的例子--请参见页面上的第二个代码块。使用alert()而不是console.log()。 - Faust
3个回答

326

JavaScript对象没有标准的 .each 函数,jQuery 提供了一个函数。请参见http://api.jquery.com/jQuery.each/。下面的代码应该可以工作。

$.each(object, function(index, value) {
    console.log(value);
}); 

另一种选择是使用纯JavaScript,可以像这样使用Object.keys()和数组.map()函数

Object.keys(object).map(function(objectKey, index) {
    var value = object[objectKey];
    console.log(value);
});

请参见https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Object/keyshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map,通常比使用原始的JavaScript for循环更好,除非您真正了解使用普通for循环的影响并且需要其特定特性,例如遍历属性链。

但通常,for循环不如jQueryObject.keys().map()更好。我将在下面介绍使用简单for循环可能会遇到的两个潜在问题。


因此,正如其他答案中指出的那样,纯JavaScript的替代方案为

for(var index in object) { 
    var attr = object[index]; 
}

这有两个可能存在的问题:

1. 您想检查您正在查找的属性是来自对象本身而不是原型链。可以使用hasOwnProperty函数进行检查,如下所示:

for(var index in object) { 
   if (object.hasOwnProperty(index)) {
       var attr = object[index];
   }
}

更多信息请参见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

jQuery.eachObject.keys函数会自动处理这个问题。

2 . for循环的另一个潜在问题是作用域和非闭包。这有点复杂,但是以以下代码为例。我们有一堆带有id button0、button1、button2等的按钮,并且我们想在这些按钮上设置onclick并进行console.log

<button id='button0'>click</button>
<button id='button1'>click</button>
<button id='button2'>click</button>

var messagesByButtonId = {"button0" : "clicked first!", "button1" : "clicked middle!", "button2" : "clicked last!"];
for(var buttonId in messagesByButtonId ) { 
   if (messagesByButtonId.hasOwnProperty(buttonId)) {
       $('#'+buttonId).click(function() {
           var message = messagesByButtonId[buttonId];
           console.log(message);
       });
   }
}
如果一段时间后我们点击任何一个按钮,控制台始终会显示"clicked last!"而不是"clicked first!"或"clicked middle!"。为什么?因为在执行onclick函数时,它将使用此时此刻的buttonId变量来显示messagesByButtonId[buttonId]。而此时循环已经结束,所以buttonId变量将仍然是"button2"(在最后一次循环迭代期间拥有的值),因此messagesByButtonId[buttonId]将是messagesByButtonId["button2"],即"clicked last!"。
请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures以获取有关闭包的更多信息,特别是该页面涵盖了我们示例的最后一部分。 jQuery.eachObject.keys().map()可以自动解决此问题,因为它们为我们提供了一个具有闭包的function(index, value),因此我们可以安全地使用索引和值,并确保它们具有我们期望的值。

3
“更容易的选择”并没有由你提供,只是说了这句话。 - Alexander
1
是的,我后来进行了编辑。编辑是为了澄清这一点。 - Willem Mulder
2
“更简单”并不总是“最好”的选择,因此.. - chesscov77
for...in语句已被弃用。 - Daniel Schmidt
10
@DanielSchmidt,它并没有被弃用。http://devdocs.io/javascript/statements/for...in 你所提到的是“for each (... in ...)”,它与“for (...in...)”不同。 - Willem Mulder
Map 是从另一个数组创建一个新数组的方法(例如:通过将另一个数组中的所有值乘以 2,可以创建一个新数组 array1.map(x => x * 2))。如果不想创建新数组,则可以使用 forEach 替代 map。 - Ilan Schemoul

78
for(var key in object) {
   console.log(object[key]);
}

谢谢,但是这个返回给我“true”,而不是aaa,bbb,ccc :( - Tom Mesgert
3
是的,这是打印到控制台的属性值,对于每个键(key)都是true,如果您想查看aaa、bbb、ccc,则使用 console.log(key); - Saket Patel
14
请注意,您可能想检查找到的键是来自对象本身还是来自原型链上。使用 object.hasOwnProperty(key) 检查。 - Willem Mulder
1
是的,没错,但在对象原型中添加属性总是不好的 :) 因为这会影响所有子对象,如数组、字符串等。 - Saket Patel
谢谢。它符合我的目标。 - LUISAO
不建议使用for..in循环遍历整个原型链,这几乎永远不是你想要的。请使用Object.{keys,values,entries},并遍历生成的数组。 - Dennis

-1

var object = { "a": 1, "b": 2};
$.each(object, function(key, value){
  console.log(key + ": " + object[key]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

//output
a: 1
b: 2

5
这是错误的!$.each 是 JQuery 框架! - raiserle
1
这取决于jQuery。有没有不需要jQuery的解决方案? - Blair Anderson
2
你应该为你的答案添加一个标题,指明它依赖于jQuery。 - DavidTaubmann

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