Just look at the code and you'll understand what I mean:
var aBackup = [3, 4]; // backup array
var a = aBackup; // array to work with is set to backup array
a[0]--; // working with array..
a = aBackup; // array o work with will be rested
console.log(a); // returns [2, 4] but should return [3, 4]
console.log(aBackup); // returns [2, 4] too but should return [3, 4] too
You need to make real copies of your Arrays instead of just using a reference:
var aBackup = [3, 4]; // backup array
var a = aBackup.slice(0); // "clones" the current state of aBackup into a
a[0]--; // working with array..
a = aBackup.slice(0); // "clones" the current state of aBackup into a
console.log(a); // returns [3, 4]
console.log(aBackup); // returns [3, 4]
See MDN for documentation on the slice-method
Doesn't javascript uses pointer for arrays ? Should var a = aBackup; do a copy ? otherwise the results seems normal to me...
An array is a reference type of object, so changes made to it will change the underlying value it points to, a and aBackup will point to the same value, and a change made to a will change aBackup aswell.
It is because when you do this, you are not making a copy of the array, but infact a reference to the original array.
var a IS aBackup; // if you will
When you need to do is clone the backup array.
Related
I've got 50 different lists, called list1, list2, and so forth. I also have a function which rolls a random number between 1 and 50 and then stores the value in a variable called randomNumber, and what I want to do is to access the list with a matching number.
My attempt at access the list looked like this:
document.getElementById("demo").innerHTML = list + randomNumber;
One solution would be to put all 50 lists into one list, and then use the randomNumber to access the right list through index. I am however still curious if this can be done in a way similar to what I was decribing above the code though.
Inserting the arrays into another array and accessing them by their indexes (or assigning them to property values on an object and accessing them by their associated property names) is the right approach.
The only way to reference scoped variables by strings representing their names is by using eval().
However, I will echo the linked MDN article: Don't do this.
⚠️ Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). See Never use eval()!, below.
Here's an example of using eval to reference each of the arrays below:
const list1 = [1, 2, 3];
const list2 = [4, 5, 6];
console.log(eval('list' + '1')); // [1, 2, 3]
console.log(eval('list' + '2')); // [4, 5, 6]
And here's an example of the recommended approach:
const list1 = [1, 2, 3];
const list2 = [4, 5, 6];
// As an object:
const listNames = {
list1,
list2,
};
// As an array:
const lists = [
list1,
list2,
];
console.log(listNames['list' + '1']); // [1, 2, 3]
console.log(lists[0]); // [1, 2, 3]
console.log(listNames['list' + '2']); // [4, 5, 6]
console.log(lists[1]); // [4, 5, 6]
I'm trying to delete max value from arMin and min value from arMax, but arr (is a const!) changes too! I don't know why. I am using Google Chrome version 65.0.3325.181.
'arr' is only one time declared and it shouldn't do nothing with that. I can't understand that. Tried with delete, but it's turning numbers into 'empty', but works the same and changes const too!
It's my first post, so if I do something wrong please forgive me.
const arr = [1, 2, 3, 4, 5];
let arMin = arr;
let arMax = arr;
let min = arMin.indexOf(Math.min.apply(null, arMin));
let max = arMax.indexOf(Math.max.apply(null, arMax));
arMin.splice(max, 1);
arMax.splice(min, 1);
console.log(arMin); // [2,3,4]
console.log(arMax); // [2,3,4]
console.log(arr); // [2,3,4]
The value of arr is a reference to an array.
You cannot change that. It will always be a reference to that array.
Arrays are mutable though, so you can change values in the array. const won't prevent that.
If you want arMin and arMax to be different arrays, then you need to make a copy of the array and not just copy the value of arr (which is a reference to that array).
const makes the reference constant, not the value.
You can't make arr point to something else, but you can change its values.
Note: other languages, Dart comes to mind, have the ability of specifying constant values. That's not the case of JavaScript.
When you make an array const then you can not change the reference
const arr = [1,2,3]
arr = [4,5,6] \\ Throws errors; You can not change const reference
arr[1] = 6; \\ Works fine. You are not changing the const reference. You are just mutating the array.
const x = 5; \\ Here constant is the value
x = x + 1; \\ Error. You can not change the constant value;
As a constant, you can't reassign its value, in this case, it contains the reference to the array.
But the array itself is not immutable.
An example would be:
const arr = [0,1,2,3,4,5];
arr = 'foo' // You cannot do that
arr.push(6) // That works fine. result: [0,1,2,3,4,5,6]
To complete previous answer, to make an exact copy of array instead of copying reference, you should do something like this :
const arr = [1, 2, 3, 4, 5];
let arMin = [...arr]; // We use spread operator to create new array from original one.
let arMax = [...arr];
let min = arMin.indexOf(Math.min.apply(null, arMin));
let max = arMax.indexOf(Math.max.apply(null, arMax));
arMin.splice(max, 1);
arMax.splice(min, 1);
console.log(arMin); // [1, 2, 3, 4]
console.log(arMax); // [2, 3, 4, 5]
console.log(arr); // [1, 2, 3, 4, 5]
--- EDIT 1 ---
i use TypeScript synthax to illustrate type
const arr = [1, 2, 3, 4, 5];
arr.push(6); // Is allow.
const object: {id: number, title: string} = {id: 1, title: 'Yanis'};
object.id = 2; // Is allow.
const myString: string = 'yanis';
myString = 'Jackob'; // Not allow.
How can I create a new array without doing for each? The new array should be as follows
labels : ["Direct", "Organic Search", "Referral"]
any suggestion using javascript?
Ok. Don't want Array.forEach()? Try using Array.map function with ES6 arrow function expression for such case:
// supposing arr is your initial array
var labels = arr.map((v) => v[0]);
console.log(labels); // ["Direct", "Organic Search", "Referral"]
It's not possible to do this without any kind of loop, but as you're suggesting, a manual iteration like a foreach isn't what you're looking for, indeed.
Array.prototype.map() is the function you need in this case. ("under the hood", it's still a loop)
Here's how you can use map to get your desired result:
var myArray = [["a", 1, 2], ["b", 3, 4], ["c", 5, 6]];
var result = myArray.map(function(current){ // For each item in `myArray`
return current[0]; // return it's first element.
}); // And use that in `result`.
console.log(result)
Note that myArray.map does not change the value of myArray. You'll need to store the returned value from .map somewhere.
If you don't need to worry about supporting anything but the latest browsers, you can make this slightly shorter, using ES6:
var myArray = [["a", 1, 2], ["b", 3, 4], ["c", 5, 6]];
var result = myArray.map((c) => c[0]);
console.log(result)
You can try following
var arr1 = []; // your main array
var labels = arr1.map(function(item){
return item[0];
});
For reference, map
I am trying to return the largest element in a list page:
page = [1,2,3];
R.max(page); // returns a function.
R.max(-Infinity, page); // seems correct but doesn't work as expected.
I don't have the ramda package installed, so this is untested, but from the documentation max() only takes two arguments, so you would have to reduce() your array upon it:
var page = [1, 2, 3],
result = R.reduce(R.max, -Infinity, page);
// 'result' should be 3.
Use the apply function: https://ramdajs.com/0.22.1/docs/#apply
const page = [1, 2, 3];
R.apply(Math.max, page); //=> 3
I've noticed that [].concat() performs similarly to angular.copy() with arrays. For instance,
var x = [5, 2];
var y = [].concat(x);
// y = [5, 2]
x = [2, 3];
// y = [5, 2]
var z = angular.copy(x);
// z = [2, 3];
x = [6, 9];
// z = [2, 3];
Is there a key difference between [].concat() and angular.copy(src,[dest])?
angular.copy performs a deep copy of the source and places it on the destination (Both the arrays of source and dest and its contents, even reference types, points to different reference location). But when you do [].concat (Both the arrays of source and dest points to different reference and its reference type contents points to the same reference), it just returns a new array, so only think that is similar in using both angular.copy and [].concact in your example is that it assigns a new reference of the array object to the lhs variable.
But consider the situation where you have array of objects.
$scope.arr = [{name:'name1'}, {name:'name2'}, {name:'name3'}, {name:'name4'}];
$scope.arrConcat = [].concat($scope.arr); //Get a new array
$scope.arrCopy = angular.copy($scope.arr); //Get a new copy
//Now change the name property of one of the item
$scope.arr[3].name="Test";
//Now see who all have been changed
console.log($scope.arr[3].name); //Of course will output "Test"
console.log($scope.arrConcat[3].name); //Will also output "Test" because the new array items still holds the same reference of the objects.
console.log($scope.arrCopy[3].name); //Will output name4 because this contains another reference which holds the copy of the value of the object at index 3 from source array
//Push something on to the original array
$scope.arr.push({name:'name5'});
//You will see that new item is not available here, which is exactly the behaviour that you are seeing in your case because both the arrConcat and arrCopy holds its own version of array through the items in arrConcat and arr are from the same reference.
console.log($scope.arrConcat);
console.log($scope.arrCopy);
So only thing is that in your case [].concat is kind of a convenient method to get a copy of the source array since your array just has primitives, so no issues.
Example - Demo
http://plnkr.co/edit/06zLM8g34IDBLUmPtwV2?p=preview
var x = [5, 2];
var y = [].concat(x);
// y = [5, 2]
var x = [5, [5, 2]];
var y = [].concat(x);
// y = [5, 2]
Check this out, [].copy() never does a deep copy unlike angular.copy()