Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to change the original reference to an object in a function call

Tags:

javascript

I was working with an array in JavaScript and was wondering why changes I made to an array were correctly saving to localStorage, but weren't being reflected in the array past the function call. The code was the following:

function removeFromList(array, arrayName, key) {
  array = array.filter(function(element) { return element.key !== key; });
  localStorage.setItem(arrayName, JSON.stringify(array));
}

I did some googling and, through some old posts, discovered that the array was being passed by value to the function, that is, the array variable, which pointed to an array object, was being passed by value, and changing that copy did not affect the original variable that was pointing to my array object.

I came up with the following code as a workaround:

function removeFromList(array, arrayName, key) {
  arrayTemp = array.filter(function(element) { return element.key !== key; });
  for(var i = 0; i < array.length; i++) {
    if (!arrayTemp.some(item => item.key === array[i].key)) {
      array.splice(i, 1);
    }
  }
  localStorage.setItem(arrayName, JSON.stringify(array));
}

This solved my problem, and the new contents of the array was displayed in both localStorage and the array object that was pointed to by the original variable. However, I've been wondering if there is some new way introduced into JavaScript recently or an older method I did not find that would do a better job of achieving the desired result.

like image 352
Shadow Avatar asked Mar 01 '23 22:03

Shadow


2 Answers

I did some googling and, through some old posts, discovered that the array was being passed by value to the function, that is, the array variable, which pointed to an array object, was being passed by value, and changing that copy did not affect the original variable that was pointing to my array object.

Exactly right.

Is there a way to change the original reference to an object in a function call

No, JavaScript is still a purely pass-by-value language. While I suppose it's possible for that to change at some point, it hasn't as of this writing (and it seems really unlikely to me it ever will). If you do example(x) when x contains 42 (or an array reference), there still isn't any way for example to reach out and change the value of x (to 43, or to refer to a different array). If x refers to a mutable object (like an array), example can modify that object, but it can't make x refer to a whole new object.

Your workaround works by modifying the existing array. FWIW, in general it would be preferred to return the new array instead, so the caller has the option of either keeping the original or using the new one. E.g.:

function removeFromList(array, arrayName, key) {
    array = array.filter(function(element) { return element.key !== key; });
    localStorage.setItem(arrayName, JSON.stringify(array));
    return array;
}

And then when using it:

variableContainingArray = removeFromList(variableContainingArray, "nameInLocalStorage", 42);

But if you want to update in place, you don't need a temporary array:

function removeFromList(array, arrayName, key) {
    // Looping backward we don't have to worry about the indexes when we remove an entry
    for (let i = array.length - 1; i >= 0; --i) {
        if (array[i].key === key) {
            array.splice(i, 1);
        }
    }
    localStorage.setItem(arrayName, JSON.stringify(array));
}
like image 74
T.J. Crowder Avatar answered Mar 22 '23 23:03

T.J. Crowder


Instead of using a for-loop to remove the values from the argument array you can also empty it out using splice and add the filtered values:

function removeFromList(array, arrayName, key) {
  var filtered = array.filter(function(element) { return element.key !== key; });
  array.splice(0, array.length, ...filtered);
  localStorage.setItem(arrayName, JSON.stringify(array));
}

I suggest changing var to const and function(element) { return element.key !== key; } to element => element.key !== key if those features are available within your runtime environment.

like image 27
3limin4t0r Avatar answered Mar 23 '23 00:03

3limin4t0r