1

I have a function to describe my problem:

function testingFunc(value) {
  var temp = value;
  console.log("temp before:    " + JSON.stringify(temp));
  console.log("arrayTest before:    " + JSON.stringify(arrayTest));
  temp.unshift(123);
  console.log("temp after unshift:    " + JSON.stringify(temp));
  console.log("arrayTest after unshift:    " + JSON.stringify(arrayTest));
  temp.push(456);
  console.log("temp after push:    " + JSON.stringify(temp));
  console.log("arrayTest after push:    " + JSON.stringify(arrayTest));
  temp.shift();
  console.log("temp after shift:    " + JSON.stringify(temp));
  console.log("arrayTest after shift:    " + JSON.stringify(arrayTest));
  temp.pop();
  console.log("temp after pop:    " + JSON.stringify(temp));
  console.log("arrayTest after pop:    " + JSON.stringify(arrayTest));
  return temp;
}

var arrayTest = [1,2,3,4,5];
var arrayTestTwo;

arrayTestTwo = testingFunc(arrayTest);
console.log("arrayTest after testingFunc:    " + JSON.stringify(arrayTest));
console.log("arrayTestTwo:    " + JSON.stringify(arrayTestTwo));

As you can see, arrayTest will change too if temp change by using push, unshift, pop and shift to edit it's data.

But I want those function to work ONLY with temp and ignore arrayTest.

Is it possible? Also is it possible to work with object contains functions?

And why is this happen?

Trung0246
  • 689
  • 1
  • 10
  • 21

4 Answers4

5

When you assign an array to a variable (or passing it as an argument to a function), you are only storing a reference to that array. If two or more variables are referencing the same array, making changes to one will affect all the others as well:

var original = [];
var modified = original;
console.log(original, modified); // [] []

modified.push(1, 2, 3);
console.log(original, modified); // [1,2,3] [1,2,3]

The way to solve this is to make a copy of the array. To make a copy of an array, you just call array.slice():

var original = [];
var modified = original.slice();
console.log(original, modified); // [] []

modified.push(1, 2, 3);
console.log(original, modified); // [] [1,2,3]
Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • 1
    +1 for the slice() comment. This is a really quick and dirty approach to copying an array that is not talked about nearly enough. – brhardwick May 12 '17 at 17:59
2

You should have a look at concepts such as:

  1. Pure Functions: http://www.nicoespeon.com/en/2015/01/pure-functions-javascript/
  2. Immutable Patterns: https://www.sitepoint.com/immutability-javascript/
  3. Difference between value and reference: Is JavaScript a pass-by-reference or pass-by-value language?
  4. How to make a shallow copy or a deep copy: What is the difference between a shallow copy and a deep copy with JavaScript arrays?

Basically primitives are always passed by value, object are always passed by reference.

// Using Primitives:
var a = "Hello";
var b = a;

b += " World";

console.log('a', a);
console.log('b', b);


//Using References
var a = { hello: "Hello" };
var b = a;

b.hello += ' World';
console.log('a', a);
console.log('b', b);
// As you can see, because b is just a reference to a, editing b you're editing a too.

So, following what I said above, you need to make a copy of that objects:

var a = { hello: 'Hello' };
var b = Object.assign(Object.create(null), a);
//Object.assign is es-next, you need for a polyfill
b.hello += ' World';

console.log('a', a);
console.log('b', b);

Making shallow copy of arrays is a bit more easy because there are many native methods: Array.prototype.map, Array.prototype.reduce, Array.prototype.filter, Array.prototype.concat, etc...;

Community
  • 1
  • 1
Hitmands
  • 13,491
  • 4
  • 34
  • 69
0

Arrays, just like any object, are passed by reference. That means your temp is an alias to arrayTest. If you don't want to modify the array outside of the function, create a copy.

A shallow copy is all you need if you stick to .push(), .pop(), .shift() and .unshift(), because these will not change any of the array's elements, even if they are references themselves (non-primitive).

For an array shallow copy, use .slice()

Reading the description will help: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

0

There are some popular libraries to circumvent that problem for Arrays, Objects. etc., for example immutable.js from Facebook.

cseelus
  • 1,447
  • 1
  • 20
  • 31