I have a function which reads Files from the file system and stores them into an array. Afterwards I want to add a key/value pair to that element. However, the forEach loop is not executed, because apparently there is no element in there.
readFilesFromDirectory(folder, elements, 'json', function(){
log(Object.keys(elements).length,0);
log(elements.length,0);
elements.forEach(function(elem){
elem["newKey"] = 1;
});
});
My log contains the following lines:
1
0
The first length method is working, the second is not.
I would like to know what I am doing wrong for the second function and how I can fix it.
Actually, my main objective is to add the new key. However, I do not know how to use some Object.keyValues(elements).forEach(function(elem){...} in my code. If you have a hint for that, this would also be nice.
I would really appreciate some insight here! :-)
The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
Object.keys returns an array whose elements are strings corresponding to the enumerable properties found directly upon object. The ordering of the properties is the same as that given by looping over the properties of the object manually.
var arr = ["a", "b", "c"];
alert(Object.keys(arr)); // will alert "0,1,2"
// array like object
var obj = { 0 : "a", 1 : "b", 2 : "c"};
alert(Object.keys(obj)); // will alert "0,1,2"
// array like object with random key ordering
var an_obj = { 100: "a", 2: "b", 7: "c"};
alert(Object.keys(an_obj)); // will alert "2, 7, 100"
// getFoo is property which isn't enumerable
var my_obj = Object.create({}, { getFoo : { value : function () { return this.foo } }});
my_obj.foo = 1;
alert(Object.keys(my_obj)); // will alert only foo
Related
This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 2 years ago.
I started to learn JavaScript, and I can not catch one thing.
myDog.name = "Happy Camper";
myDog["name"] = "Happy Camper";
and also
var myDog = {
"name" : "Coder",
"legs" : 4,
"tails" : 1,
"friends" : ["everything!]"
};
here in everything - what is the difference with and without brackets?
Thank you.
In JavaScript, [] is used to determine an Array literal, but is also one of the ways to call Object keys, hence your confusion.
const myArray = []; // Returns an empty array
const someObjectValue = myObject["myKey"] // returns the value of an object's key
Please note you can also fetch an object value by using dot instead of brackets:
// They are the same thing.
const value = myObject["myKey"];
const sameValue = myObject.myKey;
They're basically two different ways of achieving the same thing.
There is one difference, thought. With brackets you can assign otherwise non-allowed keys to objects.
Example:
const myObject = {};
// Set
myObject.0 = "Hello!"; // throws error
myObject[0] = "Hello!"; // works!
myObject.some-key = "Hello!"; // throws error
myObject["some-key"] = "Hello!"; // works!
// Get
const value = myObject.0; // throws error
const value = myObject[0]; // works!
const value = myObject.some-key; // throws error
const value = myObject["some-key"]; // works!
In the first case you are accessing data inside an object passing the key inside the brackets, in the second one using the brackets you are declaring an Array in javascript which is a list of data.
Checkout this definition of array:
Arrays are list-like objects whose prototype has methods to perform
traversal and mutation operations. Neither the length of a JavaScript
array nor the types of its elements are fixed
You could add more items into your array like:
var myDog = {
"name" : "Coder",
"legs" : 4,
"tails" : 1,
"friends" : [
"everything!",
"a little more",
"one more thing",
1,
"the previous element was a number",
"the next will be an object",
{name: "test"}
]
};
You can also access array data passing the key value inside brackets like objects but array keys are ordered numbers called index, for example.
const myArray = ["a", "b", "c"]
console.log(myArray[0]) // a
console.log(myArray[1]) // b
console.log(myArray[2]) // c
Click here for more info about arrays
I have a huge object that contains the entire ESV Bible. I am trying to get a random book of the Bible whenever I press a button. Here is a small sample of the object.
var esvObject = {
"Genesis": {
"1": {}
"2": {}
"3": {}
},
"Exodus": {
"1": {}
"2": {}
"3": {}
}
}
Here is the code that I am using to get a random book.
var randNum = Math.floor(Math.random() * 66);
var randBook = esvObject[randNum];
var output = randBook;
I would expect this to work, but the output I always get is "undefined," where as I would like the output to be "Genesis" or "Exodus" etc. Getting the random number works, but if
randNum = 1
then
randBook = esvObject[1]
the output returns as "undefined" and I don't know why.
Well the reason you get undefined is that your object is of the structure:
let esvObject = {
bookName: {
1 : {}
}
}
Using bracket [] notation on a javascript object finds the matching key for the name and returns it's value. In your top level object (the one with bookNames for keys), you have to use a valid book name like Genesis. To do so, leverage the Object.keys function of javascript to get an array of all the keys in your object.
You can then use [] notation, which has a different semantic on arrays.
let books = Object.keys(esvObject); // ["Genesis", "Exodus", ...]
let randomKey = books[randNum] // this is an array, so index access works
let book = esvObject[randomKey] // matches on the bookname
And to tie it all together, esvObject["Genesis"][1] would have been valid because the object stored as "Genesis" has a property 1
You are generating random number. And then trying to pick property using that number.
But you object has properties Genesis and Exodus not 1 or 20 etc.
What you need to do is Object.getOwnPropertyNames(esvObject)
that will give you array of the property names. In this case ['Genesis', 'Exodus'] and then you need to pick random element from that array
It would not work because it does not know that the first book is named "Genesis".
To be able to use numbers from the random function you will need to use array from the keys of the object
var keys = esvObject.keys( obj );
randBookKey = keys[randNum]
randBook = esvObject[randBookKey]
esvObject (as you show it) does not have any integer keys. So you need to select a random (existing) key instead:
esvObject[Object.keys(esvObjects)[Math.floor(Math.random() * 66)]]
You're confusing accessing an array with accessing an object.
An array:
arr = ["genesis", "exodus"]
is accessed like this:
arr[0] // genesis
An object:
obj = { "genesis" : "foo", "exodus" : "bar"}
is accessed like this:
obj["genesis"] // foo
To achieve what you want to do, see Access non-numeric Object properties by index?
Task: convert an array into an object with one key-value pair, where the first array item is the key, and the last array item is the value.
E.g., [1,2,3] should convert to {1: 3}
I can't get it to work as:
function transformFirstAndLast(array) {
var firstLast = {
array[0]: array[-1]
};
return firstLast
}
But only as:
function transformFirstAndLast(array) {
var firstLast = {};
firstLast[array[0]] = array[array.length - 1];
return firstLast
}
...why doesn't the first work? Why can't you index the array for the key & value?
You could pop the last element and take a computed property for the object. (For the first element, you could take Array#shift, if you like to do it in the same manner.)
function transformFirstAndLast(array) {
return { [array[0]]: array.pop() };
}
console.log(transformFirstAndLast([1, 2, 3]));
ES5 with a temporary variable.
function transformFirstAndLast(array) {
var temp = {};
temp[array[0]] = array.pop();
return temp;
}
console.log(transformFirstAndLast([1, 2, 3]));
Take the first is easy, take the last is the size minus one like this:
function firstAndLast(array) {
var ary = {};
ary[array[0]] = array[array.length - 1];
return ary;
}
console.log(firstAndLast([1,2,3]))
First, you must remember than an array is a type of JavaScript object and, in JavaScript, an object property (a.k.a. "key") can be accessed or assigned in two ways:
via "dot notation"
object.property = value;
via array syntax
object["property"] = value;
Next, remember that, in JavaScript, if you assign a value to a property that doesn't exist (using either syntax from above), the property will be created, like in the following:
console.log(window.someNewProperty); // undefined
window.someNewProperty = 17; // This causes the property to be created
window["someOtherNewProperty"] = "Voilla!"; // So does this, just with array syntax
console.log(window.someNewProperty); // 17
console.log(window["someOtherNewProperty"]); // "Voilla!"
Now, moving on to the specifics of an array, it's critical to understand the difference between an object property/key name (which is always represented as a string) and an array index (which is always a non-negative integer up to the max integer in JavaScript). So, if you have an array and seemingly assign a value to a negative index, you are actually creating a property that is named the negative index and not actually adding to the length of the array or making a new indexed position in the array. We can see that here:
var myArray = ["a", "b", "c"];
myArray[-1] = 15;
console.log(myArray.length); // 3 not 4
console.log(myArray[-1]); // 15
// Now to prove that -1 is a string name for a new property and not an index:
console.log(myArray); // Notice no 15 in the indexed values?
// And, if we enumerate the object (not just the indexes), we'll see that we actually created
// a property with [-1], not a new index.
for(var prop in myArray){
// Note that prop is not the value of the property, it's the property name itself
console.log(typeof prop, prop, myArray[prop]);
}
So, to sum up, Arrays have non-negative integer indexes to store the items that make up the length of the array, but Arrays are also objects and have properties, like all other objects do. Any bracket assignments that use anything other than non-negative integers as the key name will become new properties, not array indices.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between an array and an object?
The item exists in the array but it says that the array is 0 length?
I m a bit confused in object and associative array in javascript. I read this :question but this question says that there is not much of a difference in both. I wrote this in the console:
var a = [];
a["A"] = 1;
var b = {};
b["B"] = 2;
var c = new Object();
c["C"] = 3;
output for above are as:
a gives {A : 1}
b gives {B : 2}
c gives {C : 3}
All above three cases gives same reault as in they all gives an object. Question is how all above 3 cases are treated in javascript.
An array is also an object, that's why you can use non-numeric indices also. Those will be added as properties to the array object, not part of the array data.
The difference between an array and an object, is that the array counts properties with a numeric index as being part of the array data, and updates the length property accordingly. (Also the Array object has some specific methods to work with the array data.)
var a = [];
a[42] = 1337;
Now the length has changed to include the item:
alert(a.length); // shows 43
Using strings or numbers as index doesn't matter, a numeric index counts even if it's a string:
alert(a[42]); // shows 1337
alert(a["42"]); // shows 1337
Reducing the length removes the properties outside it:
a.length = 10;
alert(a[42]); // shows undefined
In your example, b and c are essentially the same thing, because {} is the equivalent of new Object().
Coming back to a, it's defined as an Array which is a special kind of Object in the sense that numeric properties (based on uint32) are treated differently. Its length property gets updated when those properties are added and removed.
When you use 'A' as an index, it gets treated as a regular property, defined by how Object works with properties, so you can access it as a.A or a['A'] whereas an index of [5] can only be accessed using a[5].
Normally, the debug output of an array is always [] unless the length property is non-zero, so the output you've shown is somewhat irregular.
Trivia
According to the ECMAScript documentation, a particular value p can only be an array index if and only if:
(p >>> 0 === p) && (p >>> 0 !== Math.pow(2, 32) - 1)
See also:
The item exists in the array but it says that the array is 0 length?
Let's start by clarifying something:
new Object() is the same as {}
new Array() is the same as []
The latter are just shortened forms of the former.
Behind the scenes, everything in javascript is basically an object (this is an exaggeration but fairly accurate). Arrays are simply derived from objects. Here's a fairly rudimentary example of what an Array REALLY looks like:
var myArray = {};
myArray[0] = 'value1';
myArray[1] = 'value2';
myArray[2] = 'value3';
myArray[length] = 3;
The prototype of an array contains all the methods. For example:
// myArray#push
myArray.prototype.push = function(val){
myArray[this.length] = val;
this.length++;
}
Another way to illustrate this is to take an array and add keys that are not numeric:
var example = [];
example.push(0);
example.push(1);
example.push(2);
example['a'] = 'a';
example['b'] = 'b';
example['c'] = 'c';
example.log = function(){
for(var i = 0, l = this.length; i < l; i++){
console.log( example[i] );
}
console.log(this['a']);
console.log(this['b']);
console.log(this['c']);
}
// example[0] is 0
// example[1] is 1
// example[2] is 2
// example.log is my custom function
example.log(); // results in
// 0
// 1
// 2
// a
// b
// c
Also, don't always believe everything the console tells you. For example, if you do this:
var console_confusion = {};
console_confusion.length = 100;
console_confusion.splice = function(){ /* do absolutely nothing */ };
console.log( console_confusion );//results in
//
// in Chrome:
// [undefined × 100]
//
Chrome will interprut anything with a numeric length property and a splice function as an Array. This is why jQuery objects look like Arrays in the console.
Please read the following article – http://www.2ality.com/2012/12/arrays.html
In short, “regular arrays”, denoted as [] in JavaScript, are also objects, just like {}, but they have length property and “numeric” keys (“indicies”), plus their internal __proto__ property points at Array.prototype object, which holds all Array methods, such as push or forEach etc.
first is an array
second is an object array
third is an array object
This is a method I tried to run:
function SayHello() {
cars = new Array();
cars[0] = "Toyota";
cars[1] = "Mitsubishi";
cars[2] = "Honda";
for (car in cars) {
alert(car);
}
}
This returned:
0
1
2
When I changed the code to this:
function SayHello() {
cars = new Array();
cars[0] = "Toyota";
cars[1] = "Mitsubishi";
cars[2] = "Honda";
for (car in cars) {
alert(cars[car]);
}
}
It returned the names correctly.
My question is, does the for-in loop just return an index in an orderly fashion? Thanks.
Yes, the value of the iterator is the name of the property. It's highly frowned upon to use it to loop over arrays, however. For example, consider this:
x = ['a', 'b', 'c'];
x.foo = 'bar';
for (i in x) alert(i); // 0, 1, 2, foo
It's intended for iterating over the members of an object:
x = { a : 'apple', b : 'banana', c : 'carrot' };
for (i in x) {
// and it's best to check that the property actually exists
// on this object, not just on one of its prototypal ancestors:
if (x.hasOwnProperty(i)) {
alert(i); // 'a', 'b', 'c'
}
}
More information about why on the YUI Blog
Yes, it will be the index within the collections.
See here:
var mycars = ["Saab", "Volvo", "BMW"];
for (var car in mycars)
{
document.write(mycars[car] + "<br />");
}
As you can see, the use of the variable as an index into the collection.
You can use for each ... in syntax (introduced in Javascript 1.6) that will iterate over values. See here.
for each...in - similar to for...in, but iterates over the values of object's properties, rather than the property names themselves. (New in JavaScript 1.6.)
As far as I know, Javascript 1.6+ is only used in Firefox at this time.
Yes and no. It returns indexes, not the values, and it returns them as quoted strings. "0", "1", etc..
The plus side of this is that for in works the same if you use a javascript object as associative array.
It returns the "key" of each item. Same result will be achieved with such "array":
cars = {0: "Toyota", 1: "Mitsubishi", 2: "Honda"};
use the regular for...
for (var i = 0; i < cars.length; i++) {
let car = cars[i];
// Do what you want from here
}
for...in - iterates over all enumerable properties of an object that are keyed by strings (for simple arrays it returns the element's index).
for...of - iterates over the property values but can only be used for iteratable types: built-in String, Array, array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined iterables (not for generic objects).