Creating array of arrays different behavior [duplicate] - javascript

This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 6 years ago.
I have found that these two different methods of creating an array of arrays produce different behaviors:
// Method 1
for (var arr1 = []; arr.push([]) < len;) {}
// Method 2
var arr2 = new Array(len).fill([])
The arrays created look the same in the console, however they behave differently in my code. What could be causing this?

The difference is that in the 1st method each index points to a different array, while in the Array#fill all indexes point to the same array.
Note: the 1st method will not create an array of arrays
var len = 3;
var arr1 = [];
// Method 1
for (var arr1 = []; arr1.push([]) < len;) {} // new sub array is pushed into arr1
// Method 2
var arr2 = new Array(len).fill([]) // each place in the array is filled with a reference to the same array
arr1[0].push(1); // push to the 1st element of arr1
arr2[0].push(1); // push to the 1st element of arr2
console.log('arr1: ', JSON.stringify(arr1)); // only the 1st sub array contains 1
console.log('arr2: ', JSON.stringify(arr2)); // all sub arrays contain 1

Update: While the answer below is technically accurate, and is another difference between the two methods, #Ori Drori's answer is almost certainly what the OP is looking for.
I'll take a stab at this, but more context would be helpful.
In common practice, these two statements typically behave the same, but there is a key difference - when you use the new keyword, the Javascript interpreter calls the Array constructor.
If you were to overwrite the Array constructor, this would only apply to arr2 which was defined with the new keyword. arr1 created with the array literal would still be a Javascript array.
As an example, let's say I wrote the following code:
function Array() {
}
Method 1 would still work, but Method 2 would return a TypeError indicating that fill is not a function.
Interestingly, using the Array literal (Method 1) still calls the Array constructor, so if I did a console.log("test"); within the Array construction this would still be printed to the console when using either method. BUT, when the Array literal (Method 1) is used, the object itself still remains a standard Javascript array even if the Array constructor is overwritten.

Related

Is there a way to splice out elements of an array and return the spliced array in one line? [duplicate]

This question already has answers here:
Js remove element from array without change the original
(4 answers)
Closed 13 days ago.
If I have an array a = [1,2,3,4] and I want to return it with the 3 removed, there are two ways I can do it:
let b = [...a] // or a.slice()
b.splice(2,1)
return b
or
return [...a.slice(0,2), ...a.slice(3,4)]
Advantage of the second is that it's one line. Disadvantage is that it's verbose. I thought of writing a helper function that contains the logic of the first approach, so that I'd be able to call it in one line elsewhere.
Is there an alternative? Something like splice but that returns that spliced array rather than mutating it and returning the spliced-out elements.
Since you know the indicies you want to remove, you can use the Array.prototype.filter method.
const a = [1,2,3,4];
const b = a.filter((_, i) => i !== 2);
console.log(b);
If you need to remove a range, you can just do something like 2 < i || i > 3.
.filter makes a copy of the array, copying the values where the callback function evaluates truthy and ignores the values where the callback function evaluates falsy.

Why pushing undefined to an empty array give 1? [duplicate]

This question already has answers here:
Why does Array.prototype.push return the new length instead of something more useful?
(6 answers)
Closed 4 months ago.
If I do
var a = [].push(undefined);
console.log(a);
it gives output as 1 even though undefined was pushed to the array. Any idea why?
You're testing it the wrong way. a is not defined as the array, as I think you suppose it to be. Try this:
var a = []
a.push(undefined);
console.log(a);
You are assigning the return value of push function to variable a. push returns the length of the array after pushing the current element in context. So, it returns 1 after pushing undefined in the array.
its pushing the length of array inside not the elements
example
var a = [].push(5,6,7,8);
console.log(a); //gives 4
Push returns the new length of the array, and thats what is stored in a
There was no explicit check has been done when assigning a new property to array object. Assigning a new property in the sense, setting 0,1,2..n properties with values, based on the length of the array.
Repeat, while items is not empty
Remove the first element from items and let E be the value of the element.
Let setStatus be Set(O, ToString(len), E, true).
ReturnIfAbrupt(setStatus).
Let len be len+1.
You can see it here. Step 8.

JavaScript: store function method to variable [duplicate]

This question already has answers here:
JavaScript Function Context Incorrect
(3 answers)
Closed 7 years ago.
I have a variable a that can be either an object or an array of objects. I have an array array.
I want to append a to array, so I thought of using either Array.prototype.push.call or Array.prototype.push.apply with a ternary operator as follows:
var a = "hello"; // or var a = ["hello", "world"];
var array = [];
var append = ($.isArray(a)) ? Array.prototype.push.apply : Array.prototype.push.call;
append(array, a); // Uncaught TypeError: undefined is not a function
($ being jQuery)
I'm new to JavaScript and I guess there is a good reason why this doesn't work but I couldn't find it. Can't apply or call be assigned to a variable? (They are not real functions?) Or is something missing on the call to append()?
Note: I know I could do this with if/else but I'd rather like to understand why I can't assign these methods to a variable and call it.
Minor additional question: I want to do this because I get a from a JSON API and if I understand correctly, JSON can't contain arrays of one single object. Although I feel that what I'm trying to do must be very common, I also couldn't find how other developers deal with this. Is there a better way than testing whether a is an array or not and use apply() or not accordingly?
This happens because call and apply are instance methods. They are critical to the context object this.
Eventually you should execute append.call(Array.prototype.push, array, a) because call or apply need function push to be passed as this
You don't need any if, just use concat
var array = [];
var a = "hello"; // or var a = ["hello", "world"]
array = array.concat(a);

Array gets modified if another one does [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 9 years ago.
It's really strange, I'm modifying one of the arrays and the other one gets modified! I found no way of making it work other than typing two times the array. What can I do?
function test(a,b,c,d)
{
this.a=a;
this.b=b;
this.c=c;
this.d=d;
}
var data0=data=[[1,2,3,4],[5,6,7,8]];
function construct(constructor,args)
{
function F(){return constructor.apply(this,args);}
F.prototype=constructor.prototype;
return new F();
}
for(var i=0,l=data.length;i<l;i++)
{
data[i]=construct(test,data[i]);
}
console.log(data0);
http://jsfiddle.net/mageek/3GNMC/2/
You are referencing the same items:
var data0=data=[[1,2,3,4],[5,6,7,8]];
(and as a side note - here data ends up on the global object as it isn't really declared, only data0 is)
If you want to generate two different arrays with identical items you can do this:
var data0 =[[1,2,3,4],[5,6,7,8]];
var data = [];
data = data.concat(data0);
or
data = data0.slice(0);
JavaScript will not copy arrays upon data0=data assignment, instead it will point both variables to the same object in memory. You need to actually clone the array fully, for example:
var data0 = data.slice(0);

Check Length of Multidimensional Arrays with Javascript [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Length of Javascript Associative Array
I want to check the length of a multidimensional array but I get "undefined" as the return. I'm assuming that I am doing something wrong with my code but I can't see anything odd about it.
alert(patientsData.length); //undefined
alert(patientsData["XXXXX"].length); //undefined
alert(patientsData["XXXXX"]['firstName']); //a name
fruits = ["Banana", "Orange", "Apple", "Mango"];
alert(fruits.length); //4
Thoughts? Could this have something to do with scope? The array is declared and set outside of the function. Could this have something to do with JSON? I created the array from an eval() statement. Why does the dummy array work just fine?
Those are not arrays. They're objects, or at least they're being treated like objects. Even if they are Array instances, in other words, the "length" only tracks the largest numeric-indexed property.
JavaScript doesn't really have an "associative array" type.
You can count the number of properties in an object instance with something like this:
function numProps(obj) {
var c = 0;
for (var key in obj) {
if (obj.hasOwnProperty(key)) ++c;
}
return c;
}
Things get somewhat messy when you've got inheritance chains etc, and you have to work out what you want the semantics of that to be based on your own architecture.
.length only works on arrays. It does not work on associative arrays / objects.
patientsData["XXXXX"] is not an array. It's a object. Here's a simple example of your problem:
var data = {firstName: 'a name'};
alert(data.length); //undefined
It appears that you are not using nested array, but are using objects nested within objects because you're accessing members by their names (rather than indexes).

Categories

Resources