This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
JavaScript foreach Vs for
What's the difference between a for loop and for...in? I mean, if there is a difference, it can't be much.
And, I see within validation scripts sometimes the function written like:
function check() {
with(something) {
if(){
// do something
}
}
}
What's the point of the "with" condition?
The for each..in statement iterates a specified variable over all values of an object's properties. For each distinct property, a specified statement is executed. This was introduced by Mozilla in JavaScript 1.6 (see comment by #CMS below), and is not supported in all mainstream browsers.
For each example:
var sum = 0;
var obj = {prop1: 5, prop2: 13, prop3: 8};
for each (var item in obj) {
sum += item;
}
console.log(sum); // prints "26", which is 5 + 13 + 8
A similar statement is for..in, which iterates over the property names instead of property values. The same example written using for..in:
var sum = 0;
var obj = {prop1: 5, prop2: 13, prop3: 8};
for (var prop in obj) {
sum += obj[prop];
}
console.log(sum); // prints "26", which is 5 + 13 + 8
The for..in statement has been around since JavaScript 1.0, so you're safe to use it in all browsers.
These statements are different from the traditional for loop, since they are used to iterate over the properties of an object. A for loop can be used to iterate over the elements of an array, but it cannot be used to iterate over the properties of an object, unless you can use ECMAScript 5's Object.keys, which could be used to implement the above example as follows:
var sum = 0;
var obj = {prop1: 5, prop2: 13, prop3: 8};
var keys = Object.keys(obj)
for (var i = 0; i < keys.length; i++) {
sum += obj[keys[i]];
}
console.log(sum); // prints "26", which is 5 + 13 + 8
As for the with statement, note the following:
JavaScript looks up an unqualified name by searching a scope chain associated with the execution context of the script or function containing that unqualified name. The 'with' statement adds the given object to the head of this scope chain during the evaluation of its statement body. If an unqualified name used in the body matches a property in the scope chain, then the name is bound to the property and the object containing the property. Otherwise a 'ReferenceError' is thrown.
Therefore, consider the following:
var prop1 = 10;
var obj = {prop1: 5, prop2: 13, prop3: 8};
with (obj) {
console.log(prop1); // prints 5 instead of 10
}
Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.
for each (var i in obj) iterates over the values of an object while for(var i in obj) iterates over the properties. Use it for objects only!
You need a for...in... loop to iterate over properties of an object. A normal for loop would not help you here.
The with statement pushes the properties of the provided object at the beginning of the scope chain. In your example, if something has a property foo, then you can access this property inside the with body just with foo (instead of something.foo).
But note that all other variables, like local variables are now farther down the scope chain, which makes accessing them potentially slower.
Most books and experts recommend to not use with.
Related
I'm reading the book Understanding EMCAScript 6 and I came across a strange line that I can't decipher. result[keys[i]] = object[keys[i]];
I know that ...keys is a rest parameter. However I can access a rest parameter using standard array syntax, for example keys[i]. What does [keys[i]] mean? I googled and I can't find anything. It looks like an array but I'm not sure what type of array or how it works. Just knowing the name would be a huge help. It's from this code.
function pick(object, ...keys) {
let result = Object.create(null);
for (let i = 0, len = keys.length; i < len; i++) {
result[keys[i]] = object[keys[i]];
}
return result;
}
It's no magic, just nested property access using bracket notation.
result[ keys[i] ] = object[ keys[i] ];
could also be written
const key = keys[i];
result[key] = object[key];
To understand this function, you have to understand that, in JavaScript objects are just hashes. object.foo is just syntactic sugar for object["foo"].
This means that you can dynamically get and set object properties, which is what this function is doing.
The keys value is an array of the arguments passed to the function. Therefore, the for loop iterates over every value in keys.
The expression keys[i] means ith element of keys.
The expression object[key] means the property of the object named key. For example, if key = "foo", then writing object[key] is the same as writing object.foo.
This means that the for loop in the function:
Looks up the object property matching the given argument;
Creates a new property in result with the same name, and assigns the value of the property to it
Therefore, the pick function can be used to select certain attributes from an object:
pick({x: 1, y: 2, z: 3}, "x", "z") // -> {x: 1, z: 3}
I was editing Chrome's sample oauth contacts extension
when I came across an interesting for-loop in line 7 of contacts.js:
for (var i = 0, contact; contact = contacts[i]; i++) {
variable i was never used in the body of the for loop, so it seemed like a typical "for...in" loop. I tried replacing the for-loop with
for (contact in contacts) {
but when I ran the extension, all my contacts came back undefined
Here is the full for-loop from the extension
for (var i = 0, contact; contact = contacts[i]; i++) {
var div = document.createElement('div');
var pName = document.createElement('p');
var ulEmails = document.createElement('ul');
pName.innerText = contact['name'];
div.appendChild(pName);
for (var j = 0, email; email = contact['emails'][j]; j++) {
var liEmail = document.createElement('li');
liEmail.innerText = email;
ulEmails.appendChild(liEmail);
}
div.appendChild(ulEmails);
output.appendChild(div);
}
What the code given does
What that does is evaluate what contacts[i] is and whether it is truthy or not, while at the same time caches the array element of the applicable index.
It's equivalent to the following code (note that in this example ++i has the same side effect as i++):
for (var i = 0; contacts[i]; ++i)
{ var contact = contacts[i];
// use contact
}
This could be interpreted as something like the following:
If !contacts[i] is false (i.e. it is truthy) continue the loop.
Otherwise, end the loop (it is falsy).
If the goal of that code was to iterate through all of an array, the problem would be that if you wanted to iterate through an element but it was falsy, it would end the entire loop instead of performing the (likely) intended effect. Take this example:
var foo = [1, 3, 5, 7, 9, 0, 2, 4, 6, 8];
// example for-loop given
for (var i = 0; foo[i]; ++i)
{ var bar = foo[i];
console.log('example: ' + bar);
}
// "normal" way of iterating through array
for (var i = 0, l = foo.length; i < l; ++i)
{ var bar = foo[i];
console.log('normal: ' + bar);
}
You'd find that the example only logs up to the number 9, while the "normal" way goes through the entire array. Of course though, if you could guarantee that all values within the array would be truthy (e.g. all array elements are objects), then this isn't that much of an issue.
What for-in does and why it doesn't work
You tried to replace that code with the following:
for (contact in contacts) { /*code here*/ }
However, this doesn't work for a number of reasons:
contact is a string of the property name, not the value of it. Take this example:
var foo =
{ bar1: 1
, bar2: 2
, bar3: 3
, bar4: 4
, bar5: 5 };
for (var i in foo) console.log(i);
What you get back is the property name (i.e. "bar1, bar2...") instead of the value. To do so for an object, you'd have to do something like the following:
for (var i in foo)
{ var bar = foo[i];
console.log(bar);
}
Now you should get back "1,2,3,4,5" on separate lines. If you got that, and some other things, you might be have defined items on Object.prototype - which is why it's generally a bad idea, unless it really makes the code cleaner, and there is a substantial purpose for doing so. To filter these out, add a hasOwnProperty() check:
for (var i in foo) if (foo.hasOwnProperty(i))
{ var bar = foo[i];
console.log(bar);
}
The upcoming version of ECMAScript (the "standard" version of JavaScript, minus the DOM) will have something called for-of loops, which will make it easier to do this sort of thing.
For-in loops generally aren't meant for arrays (it is possible, but it's just not a good idea usually). If you need to use for-in, you probably should be using an object instead - all arrays are objects, just that arrays have special internal length property and a few other things.
contact is an implied global, big no-no. In fact, implied globals are banned in strict mode. Use a variable declaration (inside or outside the for-in loop, doesn't matter) to solve this issue.
It's just learning about how JavaScript works and where to apply its various methods of doing things - some are more suitable than others in particular situations.
Here you are using an array,not an object.
Though using for..in outputs the same result as a normal for loop,this would be my answer.
MyRecommendation:
Use for..in for iterating over objects:
for..in iterates over properties of an object.
Note:the order of iteration is arbitary.
var Myobj = {
a: 1,
b: 2,
c: 3
};
for ( var prop in Myobj ) {
console.log(prop); // a...b...c
console.log(Myobj[prop]); // 1...2...3
}
but with this the problem is it will continue searching for enumerable properties up the prototype chain.So unless you dont use hasOwnProperty,it will iterate over local object and the prototype it is attached to.
//Improved version of above code:
for (var prop in Myobj) {
if ( Myobj.hasOwnProperty(prop) ) {
// prop is actually obj's property (not inherited)
console.log(prop); // a...b...c
console.log(Myobj[prop]); // 1...2...3
}
}
Use for loop for iteration over an array
for loop iterates over an array in sequential way.
I have an object, and I'm trying to see what's inside of it. So, I used print(object), which should possibly contain Spot: True, indicating that the cat Spot is alive. It returned [object object]. So, I tried, show(object), and I got Spot: True. I think that's right, but I'm not sure what the indexes are like. For example, I'm not sure if the keys are associative or numeric, or even if associative arrays are allowed in JavaScipt.
The reason I wonder why is because for (var cats in object){show(cats);} returns Spot. I can't find a way to locate the string 'cat' as being part of the array.
The cats in your example is a new variable that holds each object of iteration.
And yes, "associative arrays" are allowed, but they're really just objects:
var foo = {
bar: "baz"
}
alert(foo.bar);
alert(foo["bar"]);
Re: the for/in statement: it's more or less the same as the following, here using an array:
var cats;
var arr = [42, 69];
for (var i = 0; i < arr.length; i++) {
cats = arr[i];
alert(cats);
}
Or you can use for/in and it becomes:
for (cats in arr) {
alert(arr[cats]);
}
It's slightly different for arrays, but there's no "cats" in the array, either.
Fiddle
Javascript has arrays and objects. Arrays have numeric continuous indexes [0..length) and ordered while objects can have random indexes (strings, numbers) and are not necessarily ordered (depends on the implementation).
Using for(var key in obj) {} should only be used for objects and iterates over the properties the object has. You can use obj[var] to access the value of each property.
Note that it's useful to add an if(!obj.hasOwnProperty(key)) continue; check to the loop to ensure you do not hit properties introduced in the object's prototype.
If object is your object, I'm guessing it's not actually an array. The for (var x in object) could also be enumerating the elements (properties, functions, etc.) of your object.
Where does your object come from? What are show() and print()?
If I was trying to print out the properties of an object I might have something like this:
var myObject = {
property1: 'Test',
property2: 'Test2',
function1: function() {
// do something
}
};
for (var prop in myObject) {
if (myObject.hasOwnProperty(prop)) {
console.log(prop + ' = ' + myObject[prop]);
}
}
This should output the following:
property1 = Test
property2 = Test2
function1 = function() { // do something }
Here's a jsFiddle to show the example.
With that said, JavaScript doesn't really have associative arrays. What you can have is an object with property:value pairs, which is what I think you have.
I am working on this animation function but I have a problem. I can't seem to perform what should be an easy task, I can not get the length of an object. If you check out that jsFiddle you can see that I am running alert(properties.length); and it is returning undefined. Can anyone see why this might be?
This is supported in node.js and newer environments.
var obj = {a: "a", b: "b"};
Object.keys(obj).length // 2
JavaScript object simply do not have a length property, only Arrays do. If you want to know the number of properties that are defined on a object, you have to iterate over them and count them.
Also, your for in loop is prone to bugs due extension of Object.prototype since in will traverse the complete prototype chain and enumerate all the properties that are on the chain.
Example
// Poisoning Object.prototype
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // logs both 'moo' AND 'bar'
}
You have to use the hasOwnProperty method on the object in order to filter out those unwanted properties.
// still the foo from above
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i); // only logs 'moo'
}
}
Many JavaScript frameworks out there extend the prototype, not using hasOwnProperty often leads to horrible bugs.
Update
Concerning the actual problem that your code is not animation both properties.
for(var p in properties) {
...
for(var i = 0; i <= frames; i++)
{
setTimeout((function(exti, element) {
return function() {
// p gets overriden by for outer for in loop
element.style[p] = original + (pixels * exti) + 'px';
}
// you need to pass in a copy of the value of p here
// just like you do with i and element
})(i, element), i * (1000 / 60), element);
}
....
}
If you are using Underscore.js, you can use _.size():
_.size({one : 1, two : 2, three : 3});
=> 3
Objects have no length, you'll need to use an array if you want that.
If you have to find the number of properties in an object there is only one way:
var length =0;
for(var i in obj) length++;
Here's #Junaid Qadir Shekhanzai's general function for "finding the length of an object" (which as we're told, should properly be called "counting the properties of an object"). It combines solutions from #Ivo Wetzel and #Martin Jespersen:
function countProperties(myObj){
var length = 0;
if(typeof myObj != 'object'){
return false;
}
for(var i in myObj) {
length++;
}
return length;
}
This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 6 years ago.
How do I enumerate the properties of a JavaScript object?
I actually want to list all the defined variables and their values, but I've learned that defining a variable actually creates a property of the window object.
Simple enough:
for(var propertyName in myObject) {
// propertyName is what you want
// you can get the value like this: myObject[propertyName]
}
Now, you will not get private variables this way because they are not available.
EDIT: #bitwiseplatypus is correct that unless you use the hasOwnProperty() method, you will get properties that are inherited - however, I don't know why anyone familiar with object-oriented programming would expect anything less! Typically, someone that brings this up has been subjected to Douglas Crockford's warnings about this, which still confuse me a bit. Again, inheritance is a normal part of OO languages and is therefore part of JavaScript, notwithstanding it being prototypical.
Now, that said, hasOwnProperty() is useful for filtering, but we don't need to sound a warning as if there is something dangerous in getting inherited properties.
EDIT 2: #bitwiseplatypus brings up the situation that would occur should someone add properties/methods to your objects at a point in time later than when you originally wrote your objects (via its prototype) - while it is true that this might cause unexpected behavior, I personally don't see that as my problem entirely. Just a matter of opinion. Besides, what if I design things in such a way that I use prototypes during the construction of my objects and yet have code that iterates over the properties of the object and I want all inherited properties? I wouldn't use hasOwnProperty(). Then, let's say, someone adds new properties later. Is that my fault if things behave badly at that point? I don't think so. I think this is why jQuery, as an example, has specified ways of extending how it works (via jQuery.extend and jQuery.fn.extend).
Use a for..in loop to enumerate an object's properties, but be careful. The enumeration will return properties not just of the object being enumerated, but also from the prototypes of any parent objects.
var myObject = {foo: 'bar'};
for (var name in myObject) {
alert(name);
}
// results in a single alert of 'foo'
Object.prototype.baz = 'quux';
for (var name in myObject) {
alert(name);
}
// results in two alerts, one for 'foo' and one for 'baz'
To avoid including inherited properties in your enumeration, check hasOwnProperty():
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
alert(name);
}
}
Edit: I disagree with JasonBunting's statement that we don't need to worry about enumerating inherited properties. There is danger in enumerating over inherited properties that you aren't expecting, because it can change the behavior of your code.
It doesn't matter whether this problem exists in other languages; the fact is it exists, and JavaScript is particularly vulnerable since modifications to an object's prototype affects child objects even if the modification takes place after instantiation.
This is why JavaScript provides hasOwnProperty(), and this is why you should use it in order to ensure that third party code (or any other code that might modify a prototype) doesn't break yours. Apart from adding a few extra bytes of code, there is no downside to using hasOwnProperty().
The standard way, which has already been proposed several times is:
for (var name in myObject) {
alert(name);
}
However Internet Explorer 6, 7 and 8 have a bug in the JavaScript interpreter, which has the effect that some keys are not enumerated. If you run this code:
var obj = { toString: 12};
for (var name in obj) {
alert(name);
}
If will alert "12" in all browsers except IE. IE will simply ignore this key. The affected key values are:
isPrototypeOf
hasOwnProperty
toLocaleString
toString
valueOf
To be really safe in IE you have to use something like:
for (var key in myObject) {
alert(key);
}
var shadowedKeys = [
"isPrototypeOf",
"hasOwnProperty",
"toLocaleString",
"toString",
"valueOf"
];
for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) {
if map.hasOwnProperty(a[i])) {
alert(a[i]);
}
}
The good news is that EcmaScript 5 defines the Object.keys(myObject) function, which returns the keys of an object as array and some browsers (e.g. Safari 4) already implement it.
In modern browsers (ECMAScript 5) to get all enumerable properties you can do:
Object.keys(obj)
(Check the link to get a snippet for backward compatibility on older browsers)
Or to get also non-enumerable properties:
Object.getOwnPropertyNames(obj)
Check ECMAScript 5 compatibility table
Additional info:
What is a enumerable attribute?
I think an example of the case that has caught me by surprise is relevant:
var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
document.writeln( propertyName + " : " + myObject[propertyName] );
}
But to my surprise, the output is
name : Cody
status : Surprised
forEach : function (obj, callback) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
callback(prop);
}
}
}
Why? Another script on the page has extended the Object prototype:
Object.prototype.forEach = function (obj, callback) {
for ( prop in obj ) {
if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
callback( prop );
}
}
};
for (prop in obj) {
alert(prop + ' = ' + obj[prop]);
}
Simple JavaScript code:
for(var propertyName in myObject) {
// propertyName is what you want.
// You can get the value like this: myObject[propertyName]
}
jQuery:
jQuery.each(obj, function(key, value) {
// key is what you want.
// The value is in: value
});
Here's how to enumerate an object's properties:
var params = { name: 'myname', age: 'myage' }
for (var key in params) {
alert(key + "=" + params[key]);
}
I found it... for (property in object) { // do stuff } will list all the properties, and therefore all the globally declared variables on the window object..
You can use the for of loop.
If you want an array use:
Object.keys(object1)
Ref. Object.keys()
If you are using the Underscore.js library, you can use function keys:
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
Python's dict has 'keys' method, and that is really useful. I think in JavaScript we can have something this:
function keys(){
var k = [];
for(var p in this) {
if(this.hasOwnProperty(p))
k.push(p);
}
return k;
}
Object.defineProperty(Object.prototype, "keys", { value : keys, enumerable:false });
EDIT: But the answer of #carlos-ruana works very well. I tested Object.keys(window), and the result is what I expected.
EDIT after 5 years: it is not good idea to extend Object, because it can conflict with other libraries that may want to use keys on their objects and it will lead unpredictable behavior on your project. #carlos-ruana answer is the correct way to get keys of an object.
If you're trying to enumerate the properties in order to write new code against the object, I would recommend using a debugger like Firebug to see them visually.
Another handy technique is to use Prototype's Object.toJSON() to serialize the object to JSON, which will show you both property names and values.
var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
Object.toJSON(data);
//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
http://www.prototypejs.org/api/object/tojson
I'm still a beginner in JavaScript, but I wrote a small function to recursively print all the properties of an object and its children:
getDescription(object, tabs) {
var str = "{\n";
for (var x in object) {
str += Array(tabs + 2).join("\t") + x + ": ";
if (typeof object[x] === 'object' && object[x]) {
str += this.getDescription(object[x], tabs + 1);
} else {
str += object[x];
}
str += "\n";
}
str += Array(tabs + 1).join("\t") + "}";
return str;
}