I have three variables a, b and c. I have to insert these into an array called arr. On calling function click, these variables should get pushed into arr array. eg. if i call click with arg 1,2 & 3 then array should be [1,2,3], now when I will pass the args 6,7 then the array should be [1,2,3,6,7].
In the code below, I tried to use concat method to get the desired result but i was unsuccessful.Is there any way around this?
function click(a,b,c){
var A=a;
var B=b;
var C=c;
var arr=[]
var newArr=[A,B,C]
arr.concat(newArr);
console.log(arr);
}
click(10,11,12);
click(12,13,14);
Declare a global array outside of the function and then after push values into it.
var arr = [];
function click(a,b,c){
arr.push(a, b, c)
}
click(10,11,12);
click(12,13,14);
console.log(arr);
The problem with your code is that, you are concatenating to the array but not considering the return value.
arr = arr.concat(newArr);
Then declare the array global to hold the values for every click.
function click(arr, a, b, c){
arr.push(a, b, c);
console.log(arr);
}
var arr = [];
click(arr, 10, 11, 12);
click(arr, 12, 13, 14);
If you don't want your arr outside your function, another approach is storing your arr inside click scope then call it anywhere (it doesn't pollute your global scope):
let click = (function (arr) {
return function (a,b,c) {
var A=a;
var B=b;
var C=c;
var newArr=[A,B,C]
arr = arr.concat(newArr);
console.log(arr);
}
})([])
click(10,11,12);
click(12,13,14);
First of all. You should either define arr outside your function or pass arr into function as a parameter.
Second one. Function concat returns concatenated arrays and left original arrays unchanged. So you need something like arr=arr.concat(newArr)
Destructuring assignment can be used to functionally concatenate
variables with arrays.
See below for a practical example.
// Input.
const input = [1, 2, 3]
// Click.
const click = (array, ...arguments) => [...array, ...arguments]
// Output.
const output = click(input, 4, 5, 6)
// Proof.
console.log(output)
Your Problem here is that the concat function returns a new array instance with the elements:
Check Here
function click(a,b,c){
var A=a;
var B=b;
var C=c;
var arr=[]
var newArr=[A,B,C]
arr = arr.concat(newArr);
// concat does not change the ref itself
console.log(arr);
}
click(10,11,12);
click(12,13,14);
Related
Are there any substantial reasons why modifying Array.push() to return the object pushed rather than the length of the new array might be a bad idea?
I don't know if this has already been proposed or asked before; Google searches returned only a myriad number of questions related to the current functionality of Array.push().
Here's an example implementation of this functionality, feel free to correct it:
;(function() {
var _push = Array.prototype.push;
Array.prototype.push = function() {
return this[_push.apply(this, arguments) - 1];
}
}());
You would then be able to do something like this:
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
}
someFunction(value, someArray.push({}));
Where someFunction modifies the object passed in as the second parameter, for example. Now the contents of someArray are [{"someKey": "hello world"}].
Are there any drawbacks to this approach?
See my detailed answer here
TLDR;
You can get the return value of the mutated array, when you instead add an element using array.concat[].
concat is a way of "adding" or "joining" two arrays together. The awesome thing about this method, is that it has a return value of the resultant array, so it can be chained.
newArray = oldArray.concat[newItem];
This also allows you to chain functions together
updatedArray = oldArray.filter((item) => {
item.id !== updatedItem.id).concat[updatedItem]};
Where item = {id: someID, value: someUpdatedValue}
The main thing to notice is, that you need to pass an array to concat.
So make sure that you put your value to be "pushed" inside a couple of square brackets, and you're good to go.
This will give you the functionality you expected from push()
You can use the + operator to "add" two arrays together, or by passing the arrays to join as parameters to concat().
let arrayAB = arrayA + arrayB;
let arrayCD = concat(arrayC, arrayD);
Note that by using the concat method, you can take advantage of "chaining" commands before and after concat.
Are there any substantial reasons why modifying Array.push() to return the object pushed rather than the length of the new array might be a bad idea?
Of course there is one: Other code will expect Array::push to behave as defined in the specification, i.e. to return the new length. And other developers will find your code incomprehensible if you did redefine builtin functions to behave unexpectedly.
At least choose a different name for the method.
You would then be able to do something like this: someFunction(value, someArray.push({}));
Uh, what? Yeah, my second point already strikes :-)
However, even if you didn't use push this does not get across what you want to do. The composition that you should express is "add an object which consist of a key and a value to an array". With a more functional style, let someFunction return this object, and you can write
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
return obj;
}
someArray.push(someFunction(value, {}));
Just as a historical note -- There was an older version of JavaScript -- JavaScript version 1.2 -- that handled a number of array functions quite differently.
In particular to this question, Array.push did return the item, not the length of the array.
That said, 1.2 has been not been used for decades now -- but some very old references might still refer to this behavior.
http://web.archive.org/web/20010408055419/developer.netscape.com/docs/manuals/communicator/jsguide/js1_2.htm
By the coming of ES6, it is recommended to extend array class in the proper way , then , override push method :
class XArray extends Array {
push() {
super.push(...arguments);
return (arguments.length === 1) ? arguments[0] : arguments;
}
}
//---- Application
let list = [1, 3, 7,5];
list = new XArray(...list);
console.log(
'Push one item : ',list.push(4)
);
console.log(
'Push multi-items :', list.push(-9, 2)
);
console.log(
'Check length :' , list.length
)
Method push() returns the last element added, which makes it very inconvenient when creating short functions/reducers. Also, push() - is a rather archaic stuff in JS. On ahother hand we have spread operator [...] which is faster and does what you needs: it exactly returns an array.
// to concat arrays
const a = [1,2,3];
const b = [...a, 4, 5];
console.log(b) // [1, 2, 3, 4, 5];
// to concat and get a length
const arrA = [1,2,3,4,5];
const arrB = [6,7,8];
console.log([0, ...arrA, ...arrB, 9].length); // 10
// to reduce
const arr = ["red", "green", "blue"];
const liArr = arr.reduce( (acc,cur) => [...acc, `<li style='color:${cur}'>${cur}</li>`],[]);
console.log(liArr);
//[ "<li style='color:red'>red</li>",
//"<li style='color:green'>green</li>",
//"<li style='color:blue'>blue</li>" ]
var arr = [];
var element = Math.random();
assert(element === arr[arr.push(element)-1]);
How about doing someArray[someArray.length]={} instead of someArray.push({})? The value of an assignment is the value being assigned.
var someArray = [],
value = "hello world";
function someFunction(value, obj) {
obj["someKey"] = value;
}
someFunction(value, someArray[someArray.length]={});
console.log(someArray)
I am trying to extend Array prototype with the following functions:
Array.prototype.uniqueItems=function(){
var ar=this,unique=[],max=ar.length;
for(var i = 0 ; i < max;i++)
if(unique.indexOf(ar[i] )==-1)
unique.push(ar[i]);
return unique;
};
Array.prototype.removeDuplicates=function(){
var self = this;
self = this.uniqueItems();
return self;
};
The first function is supposed to return an array without duplicates and the second to remove all duplicates from a given array.
Consider the following code:
var x=[1,1,1,1,2,2,2,2,3,3,3,3,4,4];
x.removeDuplicates();
console.log(x);
The output is :
[ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4 ]
So the duplicates still remain.Any ideas why?Thanks In advance!!!!Also notice that I can not use x= x.uniqueItems() since it will work only for x.I want it to work for any given array.
You might as well do it like this in ES6
var x = [1,1,1,1,2,2,2,2,3,3,3,3,4,4],
u = a => Array.from(new Set(a)),
y = u(x);
console.log(y);
The new Set object in ES6 takes elements and keeps only one of each and discard the dupes. So it's in a way ideal to get unique items. A new set object is instantitated by the Set constructor and it will accept an array of items as an argument such as in var s = new Set([1,1,2,1,4,3,6,7,4,5,6,9,8,1,2,3,4,7,0]) and the resulting s set will be composed of unique entries of 1,2,4,3,6,7,5,9,8 and 0 in the order of appearance. Set objects have generator properties and iterator functions which can be obtained from them. Hence [...s] (the ES6 spread operator) or Array.from(s) would result a proper unique items array automatically.
Converting the Array to a Set and back allows for an arguably cleaner implementation:
Array.prototype.uniqueItems = function() {
return new Array.from(new Set(this));
};
Array.prototype.removeDuplicates = function() {
this.from(new Set(this));
};
Reassign to x.
var x=[1,1,1,1,2,2,2,2,3,3,3,3,4,4];
x = x.removeDuplicates();
console.log(x);
when you say
self = this.uniqueItems();
self is now pointing to a new array, not this
You need to either do
x = x.removeDuplicates();
or iterate this again in removeDuplicates to remove the other items.
For example
Array.prototype.removeDuplicates=function(){
var self = this;
var that = this;
self = this.uniqueItems();
//remove all items
for(var counter = that.length ; counter >= 0; counter -- )
{
that.splice(counter,1);
}
//copy the individual items to this
Object.keys(self).forEach(function(index){
that[index] = self[index]
});
return self;
};
Hey thank you all for your answers .I found a simple solution to my problem by doing the following:
Array.prototype.removeDuplicates=function(){
//First create a copy of the current array without duplicates
var clear_array=this.uniqueItems();
//Delete every item in the current array
this.length=0;
//Fill the current array with the elements of clear_array
for(var i = 0;i<clear_array.length;i++)
this[i] = clear_array[i];
return this;
};
Also I did not use a Set since I want to be sure about backwards compatibility
Hope this will be helpful to someone :)
Why the following code logs empty array, instead of the loaded array:
function Car() {
var parts = [];
this.parts = parts;
this.loadParts = loadParts;
function loadParts() {
parts = ['engine', 'wheels'];
}
}
var audi = new Car();
audi.loadParts();
console.log(audi.parts);
(Trying to implement the reveal pattern)
You're manipulating the closed-over local variable parts, not this.parts
Update your code to:
function loadParts() {
this.parts = ['engine', 'wheels'];
}
for more predictable results.
The problem is that your code reassign the local parts variable that it ends up pointing to a different array from this.parts.
A solution is to change the code to:
function loadParts() {
parts.splice(0, parts.length, 'engine', 'wheels');
}
this will mutate in-place the content of the same array instead.
In Javascript the code
var x = [1, 2, 3];
var y = x;
x = [4, 5, 6]
will not change the content of what y is pointing to.
This is what your code is doing (with y being this.parts).
Because you are overwriting the parts array with an entirely new array parts = ['engine', 'wheels'].
this.parts is a reference to the value of parts which is the original array parts = [];.
You either want to populate the original array:
function loadParts() {
parts.push('engine');
parts.push('wheels');
}
Or set the reference of this.parts to the new array
function loadParts() {
parts = ['engine', 'wheels'];
this.parts = parts;
}
when you assign a value to an Object/Array, it will contain the reference of the value, and it looses its own references just like what you did here :
this.parts = parts;
now when you did this :
function loadParts() {
parts = ['engine', 'wheels'];
}
parts loses its own reference and its no longer equal to this.parts, I suggest you just push data to the parts array
function loadParts() {
parts.push('engine', 'wheels');
}
I have an array with random count of elements, for example:
var array = [1, 2];
And I want to execute some function with the next parameters:
functionName(SOME_CONST, array[0], array[1])
What is the best way to do this, considering that array could have a different number of parameters?
Have a look at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply for details on how to use the Function.prototype.apply method.
So long as you want to use all of the items in your array as arguments in the function that you are calling, you can use:
function some_method(a, b, c) {}
var array = [1,2];
some_method.apply(this, ['SOME_CONST'].concat(array));
which will result in calling some_method with a being the 'SOME_CONST' and b and c being the first two elements in the array. If you had more elements in the array, they would come next in the arguments list in the some_method function.
You can just call the function and pass in the array itself instead of it's elements like this
function functionName(SOME_CONST, myArray){
//myArray contains the same elemnts here too
}
then you can call the function like this
var myArray = [1,2];
functionName(CONST_VAL,myArray);
The simplest solution would be to pass the whole array to the function and have the function iterate over it. This would allow for a variable length array.
functionName(SOME_CONST, array) {
for (var ii = 0, len = array.length; ii < len; ii++) {
// do something.
}
}
Use .apply, and array join, i mean create new array, let the SOME_CONST be the first element and join the other array which you already have.
You can do like this,
var array = [1, 2];
functionName.apply(thisObj || window, [SOME_CONST].join(array));
function functionName(a, b, c){
//a is SOME_CONST, b is 1 and c is 2
}
thisObj is the scope/context of the function which you are calling. If you dont have a thisObj just pass window object
Very simple thing I am trying to do in JS (assign the values of one array to another), but somehow the array bar's value doesn't seem affected at all.
The first thing I tried, of course, was simply bar = ar; -- didn't work, so I tried manually looping through... still doesn't work.
I don't grok the quirks of Javascript! Please help!!
var ar=["apple","banana","canaple"];
var bar;
for(i=0;i<ar.length;i++){
bar[i]=ar[i];
}
alert(ar[1]);
And, here is the fiddle: http://jsfiddle.net/vGycZ/
(The above is a simplification. The actual array is multidimensional.)
Your code isn't working because you are not initializing bar:
var bar = [];
You also forgot to declare your i variable, which can be problematic, for example if the code is inside a function, i will end up being a global variable (always use var :).
But, you can avoid the loop, simply by using the slice method to create a copy of your first array:
var arr = ["apple","banana","canaple"];
var bar = arr.slice();
copy-or-clone-javascript-array-object
var a = [ 'apple', 'orange', 'grape' ];
b = a.slice(0);
In ES6 you can use Array.from:
var ar = ["apple","banana","canaple"];
var bar = Array.from(ar);
alert(bar[1]); // alerts 'banana'
You have two problems:
First you need to initialize bar as an array:
var bar = [];
Then arr should be ar in here:
for(i=0;i<arr.length;i++){
Then you'll get alerted your banana :)
With ES6+ you can simply do this
const original = [1, 2, 3];
const newArray = [...original];
The documentation for spread syntax is here
To check, run this small code on dev console
const k = [1, 2];
const l = k
k === l
> true
const m = [...k]
m
> [1, 2]
k === m
> false
You have misspelled variable ar
Try this
for(i=0;i<ar.length;i++){
bar[i]=ar[i];
}
alert(ar[1]);
The problem probably here in the for loop statement:
for(i=0;i<ar.length;i++){
bar[i]=ar[i];
}
alert(ar[1]);
You need to fix to ar.length instead of arr.length. And it's better to initialize bar as: var bar = [].
In your code, the variable arr in the for loop is not the same as your original array ar: you have one too many r.