3

I was creating a code where I need to use some variables from a global scope, when I made my local = global, I've noticed the changes I've made in the local scope were being modified into the global scope.

This is an example of what I am talking about

global = [];
load_global();
use_global();

function load_global() {
  for (i = 0; i < 10; i++) {
    global.push(i);
  }
}

function use_global() {
  local = [];
  local = global;
  for (i = 0; i < 5; i++) {
    global.push("x");
  }
  console.log(local);
}

JSbin Example

Is there a way to use the values of a global array, but without changing it?

Niki van Stein
  • 10,564
  • 3
  • 29
  • 62
VanHalenBR
  • 35
  • 5
  • `local` is in the global scope too, you really really need to be careful with those variables (always use the `var` keyword, or `window`) to ensure it is where you expect them to be – axelduch Nov 10 '15 at 10:49
  • It is not an equality. Equality is `==` or `===`. `=` is an assignment operator. – Yeldar Kurmangaliyev Nov 10 '15 at 10:51
  • I have so many good explanations here and great help, that I don't know how to say, this one is the best, thanks all. – VanHalenBR Nov 10 '15 at 17:09

4 Answers4

1

You can try copying the global array

local = global.slice()

btw you might wanna use var keyword to make that array local. Without it the "local" array will be accessible from outside of the function

memo
  • 273
  • 2
  • 15
1

You need to clone the array into a local variable. You can do that with slice or concat for example.

To add clone to javascript arrays, you can use

Array.prototype.clone = function() {
    return this.slice(0);
};

And then

var localArray = globalArray.clone();

Also check this SO question here Javascript fastest way to duplicate an Array - slice vs for loop

Community
  • 1
  • 1
Niki van Stein
  • 10,564
  • 3
  • 29
  • 62
1

Besides old school Array#slice, you can use the ES6 method Array.from, which is designed for such scenarios:

var local = Array.from(global)

This method can be used on array-like objects or any iterable values, which don't have a slice method. You may say Array.prototype.slice.call(). Oops you are right, but isn't that annoying?

Besides, you can pass a mapping function to it as well. For example:

Array.from('asdf', c => c.toUpperCase())  // ["A", "S", "D", "F"]

Comparing to ES5 style, you can see how neat ES6 is:

Array.prototype.slice.call('asdf').map(function(c){return c.toUpperCase()})

Read MDN doc for more.

On the other hand, the method is not widely supported at the moment, you need babel or a polyfill. But ES6 is the future, eventually it'll be fully supported by all major browsers.

Leo
  • 13,428
  • 5
  • 43
  • 61
1

In Javascript, as in many other languages, you only handle references of objects. This also means that the object "inside" your array could also need to be copied. The answers based on the use of Array.slice() are excellent but it doesn't make a deep copy of the items in the array (meaning the Object element in the array are also copied so changing the state of a local object doesnt affect your global object).

One very simple (but maybe not very efficient) solution could be to serialize and deserialize your array. Ex:

var newObj = JSON.parse(JSON.stringify(obj));

Note that using JSON doesn't allow you to handle an functions. Here was an answer using this technique.

EDIT

To allow deep copy, you can also iterate the properties of the object as DMaster suggested but you should use some kine of recursion. I have taken this example from this answer in SO.

function clone(destination, source) {
    for (var property in source) {
        if (typeof source[property] === "object" && source[property] !== null && destination[property]) { 
            clone(destination[property], source[property]);
        } else {
            destination[property] = source[property];
        }
    }
}
Community
  • 1
  • 1
C.Champagne
  • 5,381
  • 2
  • 23
  • 35
  • Up to you, @DMaster but this solution is currently the only one to make a deep copy of the array which could appear to be required later. – C.Champagne Nov 10 '15 at 11:09
  • 1
    I have another solution that also copy functions: using `forEach`, with an array, simply `array.forEach(copier)`, with an object, use `Object.getOwnPropertyNames(object).forEach(copier)`. Feel free to add it in your answer if you want. – DMaster Nov 10 '15 at 11:17
  • @DMaster Thank you. I will certainly rework my answer when I have time. Your solution is cleaner but it requires more implementation effort (either specific copiers or generic ones implying recursive calls) and thus more time. – C.Champagne Nov 10 '15 at 12:38
  • there're differeces between `for...in` and `Object.getOwnPropertyNames`, I think you should mention both of them, or I will edit your post, shouldn't I? – DMaster Nov 10 '15 at 13:39