Pass variables by reference in JavaScript
Asked Answered
L

18

391

How do I pass variables by reference in JavaScript?

I have three variables that I want to perform several operations to, so I want to put them in a for loop and perform the operations to each one.

Pseudocode:

myArray = new Array(var1, var2, var3);
for (var x = 0; x < myArray.length; x++){
    // Do stuff to the array
    makePretty(myArray[x]);
}
// Now do stuff to the updated variables

What is the best way to do this?

Loma answered 12/10, 2011 at 18:18 Comment(6)
You're talking about 'pass by reference', but you have no function calls in your example so there is no passing at all in your example. Please clarify what you're trying to do.Lille
Sorry for the confusion. I didn't specifically need to write a function so 'pass by reference' was a poor choice of words. I just want to be able to perform some operations to variables without writing makePretty(var1); makePretty(var2); makePretty(var3); ... Loma
based on your comment: arr = [var1, var2, var3]; for (var i = 0, len = arr.length; i < len; i++) { arr[i] = makePretty(arr[i]); } -- you just need to store the value returned by makePretty back into the slot in the array.Droshky
For those coming from Google while searching for "pass-by-reference" or "pass-by-value" in Javascript, a good article is this from Medium: medium.com/@TK_CodeBear/…Hiss
@ErenorPaz. Medium article has gone the way of the dead parrot!Marquee
Thank you @Marquee (love your metaphore), I would then suggest something more "solid" (hopefully, given the very volatile (like a parrot, we could say) status of internet resources), from Geeks4geeks: geeksforgeeks.org/… . But, I'm sure by now there are so many references around that Google helps us better than this very comment :-) :-)Hiss
T
539

There is no "pass by reference" available in JavaScript. You can pass an object (which is to say, you can pass-by-value a reference to an object) and then have a function modify the object contents:

function alterObject(obj) {
  obj.foo = "goodbye";
}

var myObj = { foo: "hello world" };

alterObject(myObj);

alert(myObj.foo); // "goodbye" instead of "hello world"

You can iterate over the properties of an array with a numeric index and modify each cell of the array, if you want.

var arr = [1, 2, 3];

for (var i = 0; i < arr.length; i++) { 
    arr[i] = arr[i] + 1; 
}

It's important to note that "pass-by-reference" is a very specific term. It does not mean simply that it's possible to pass a reference to a modifiable object. Instead, it means that it's possible to pass a simple variable in such a way as to allow a function to modify that value in the calling context. So:

 function swap(a, b) {
   var tmp = a;
   a = b;
   b = tmp; //assign tmp to b
 }

 var x = 1, y = 2;
 swap(x, y);

 alert("x is " + x + ", y is " + y); // "x is 1, y is 2"

In a language like C++, it's possible to do that because that language does (sort-of) have pass-by-reference.

edit — this recently (March 2015) blew up on Reddit again over a blog post similar to mine mentioned below, though in this case about Java. It occurred to me while reading the back-and-forth in the Reddit comments that a big part of the confusion stems from the unfortunate collision involving the word "reference". The terminology "pass by reference" and "pass by value" predates the concept of having "objects" to work with in programming languages. It's really not about objects at all; it's about function parameters, and specifically how function parameters are "connected" (or not) to the calling environment. In particular, note that in a true pass-by-reference language — one that does involve objects — one would still have the ability to modify object contents, and it would look pretty much exactly like it does in JavaScript. However, one would also be able to modify the object reference in the calling environment, and that's the key thing that you can't do in JavaScript. A pass-by-reference language would pass not the reference itself, but a reference to the reference.

edithere is a blog post on the topic. (Note the comment to that post that explains that C++ doesn't really have pass-by-reference. That is true. What C++ does have, however, is the ability to create references to plain variables, either explicitly at the point of function invocation to create a pointer, or implicitly when calling functions whose argument type signature calls for that to be done. Those are the key things JavaScript doesn't support.)

Transcript answered 12/10, 2011 at 18:19 Comment(24)
You can pass a reference to an object or an array which allows you to change the original object or array which I believe is what the OP is actually asking about.Lille
Well, the OP used the terminology but the actual code doesn't seem to involve any "passing" at all :-) I'm not really sure what he trying to do.Transcript
This is the correct answer but not what I intended to ask. I just want to perform operations for a plethora of variables without writing: makePretty(a); makePretty(b); makePretty(c); ...etc... Solutions?Loma
You can't do that in JavaScript because you cannot create a reference to a variable; you can't create a "pointer", in other words. You can keep your variables in object containers, however, because you can effectively use property names as pointers. (Not exactly the same thing of course, but it would work.)Transcript
Passing a reference by value is not the same as passing by reference, though it may appear so in some scenarios such as this.Branny
Your blogger is wrong about C++, which does pass-by-reference, and his post makes no sense. It's irrelevant that you can't change the value of a reference after initialisation; that's got nothing to do with 'pass by reference'. His statement that 'The "pass by reference" semantic can be traced back through C#' should have rung an alarm bell.Melan
@Melan I tend to agree with you, but it's pointless hair-splitting I think. The point is that C++ makes it possible for the formal parameter list of a function to imply the need for what amounts to pass-by-reference. (So we agree here :)Transcript
@Transcript Your comment, "A pass-by-reference language would pass not the reference itself, but a reference to the reference." is actually false, especially if you're talking about C++. There is no reference to a reference implemented in the language but something else which created confusion. To stay on point, pass by reference means that inside the function, the parameter is converted to a reference to the variable in the calling scope. So when you use the variable in the function you're acting on the variable outside of the function scope.Warfield
@Paul-SebastianManole well, whether C++ is "pass by reference" is contentious; C++ people seem to think it isn't. In a real pass by reference language like old FORTRAN, it's moot because there's no such thing as a "reference" anyway. The point for this question is that in languages like JavaScript, Java, and others, there's no way to make a reference to a variable or anything like a variable, whether implicitly as part of the mechanism of function calling or explicitly with something like the C++ & operator.Transcript
@Transcript if by "is a pass by reference language" you mean implicit behavior then no, c++ is not a pass by reference language.Warfield
@Paul-SebastianManole I'm happy to agree; it's not particularly important to me because C++ is in my distant past :) I don't really know of any modern pass-by-reference languages, but then again I don't know many modern languages at all, certainly not from the research world.Transcript
@pointy This question ins't helped in part by the fact that college professors teach us that Java is "pass by reference"Beadsman
@Beadsman yes, the terminology is terrible. I have begun to wish for "pass-by-value" to become known as something like "Manhattan Parameters", and "pass-by-reference" as "Stockholm Parameters". Or something like that; anything not involving the word "reference" :)Transcript
@Transcript This is a horrible answer. If I needed help, the last thing I'd want is someone schooling me on semantic. "Pass-by-reference" simply means, "the function, to some degree, can change the value of the variable that was passed in as argument." (in the context of the question) It's really not as complicated as you make it out to be.Sadirah
@Sadirah if you spend some time reading questions here, you might find that the semantics are not at all clear to a lot of people. The answer has been upvoted 271 times, so it can't be that bad.Transcript
I think there's plenty of sentiment here on it, but wanted to add to it. The idea of passing by reference is not a concept that is replaced or modified by the existence of objects and classes. It's something that exists because of it. What predates pass by reference are pointers in which you have to clean up your own memory and pointer management becomes fundamental to programming. Managed languages (ones that have a GC and "safe" and "unsafe" memory usage) use the concept "by reference" to communicate the idea of a pointer in the managed memory space.Evan
@Lille "Passed by reference" is often used to refer to how Objects are passed but it is not entirely true. Try this in JS: (object)=>{object.x=5; object={}; object.x=6;}. object.x will be 5 in the outer scope.Eve
@Transcript cleaned up.Heller
array is not passed by reference... but its cells. if you pass an array to a function you cant be overwrite the array e.g. arr_passed = []Miraculous
@vincentthorpe the fundamental problem is that there is overlap in terminology. The word "reference", in particular, meant something to programming language theorists in the 1960s before it meant (primarily) what we think about it meaning today: a "buried" pointer. The two meanings are vaguely related, but not very much.Transcript
I find it rather deplorable that JavaScript functions cannot accept bindings and modify their values. This prevents such very useful functionality as C#''s TryGetValue() or TryParse(), which provides for a very tidy calls within if statements: if( int.TryParse(strval, out intval ).Diplomat
@Ant_222 many languages share that characteristic, Java for example.Transcript
I am surprised. All the languages I know have this very useful functionality: C, C++, C#, Modula, Modula-2, Ada, and Pascal. It is certainly easier to implement it in a script than in a real compiled language...Diplomat
Am I the only one thinking it's too much of a coincidence that the top answer to "pass by reference" was answered by someone called Pointy? :)Copestone
M
182
  1. Primitive type variables like strings and numbers are always passed by value.
  2. Arrays and Objects are passed by reference or by value based on these conditions:
  • if you are setting the value of an object or array it is Pass by Value.

     object1 = { prop: "car" };
     array1 = [1,2,3];
    
  • if you are changing a property value of an object or array then it is Pass by Reference.

     object1.prop = "car";
     array1[0] = 9;
    

Code

function passVar(obj1, obj2, num) {
    obj1.prop = "laptop"; // will CHANGE original
    obj2 = { prop: "computer" }; //will NOT affect original
    num = num + 1; // will NOT affect original
}

var object1 = {
    prop: "car"
};
var object2 = {
    prop: "bike"
};
var number1 = 10;

passVar(object1, object2, number1);
console.log(object1); // output: Object { prop: "laptop" }
console.log(object2); // output: Object { prop: "bike" }
console.log(number1); // ouput: 10
Massey answered 28/10, 2014 at 13:51 Comment(5)
That's not the meaning of "pass by reference". The term really has nothing to do with objects, but with the relationship between parameters in a called function and variables in the calling environment.Transcript
Everything is always passed by value. With non-primitives, the value that is passed is a reference. Assigning to a reference changes that reference -- naturally, since it is a value -- and thus cannot change the other object that was originally referenced. Mutating the object pointed to by a reference acts exactly as you would expect, by mutating the pointed-to object. Both scenarios are perfectly consistent, and neither magically alters how JavaScript works by going back in time and changing how they were passed into the function.Rowel
This answer clarified the previous one, which, even though it has more votes(287 at this time of writing and it is also the accepted one) was not clear enough as to how to actually pass it by reference in JS. In short, the code in this answer worked, the answer which gathered more votes did not.Peptone
That answers really get to the point of what can be done and what can't to answers OP's need. Instead of debating over what means "pass by reference", I think we can all agree that the terminology is terrible, and hope for a better one to be coined in the near future. While @Pointy's answer let me understand more the concepts, that one helped me getting the work doneThomsen
Great answer. Avoids hair-splitting back and forth on semantics, terminology and "what the OP meant" (present in some SO answers these days in order to make them complete and help with the hunt for upvotes and all), and gives very clear examples of what works and what does not. The why question and the semantical differences between one way or another is less important in this context, since you can't approach it the other way in the first place, due to how Javascript was written.Snaffle
A
30

Workaround to pass variable like by reference:

var a = 1;
inc = function(variableName) {
  window[variableName] += 1;
};

inc('a');

alert(a); // 2

And yup, actually you can do it without access a global variable:

inc = (function () {
    var variableName = 0;

    var init = function () {
        variableName += 1;
        alert(variableName);
    }

    return init;
})();

inc();
Ange answered 22/5, 2013 at 17:28 Comment(4)
@Phil it's good to be careful about global/window values, but at some point everything we are doing in the browser is a child or descendant of the window object. In nodejs, everything is a descendant of GLOBAL. In compiled object languages, that is an implicit if not explicit parent object, because doing it otherwise makes heap management more complicated (and for what?).Monometallic
@dkloke: Yes, eventually window object needs to be touched- like jQuery uses window.$/window.jQuery and other methods are under this. I was talking about pollution of the global namespace where you add a lot of variable to it rather than have them under a unifying namespace.Burundi
I can't find good words to express how bad that approach is ;(Stonemason
I love the last solution (edited version) even that it does not pass variable by reference. That is advantage because you can access the variables directly.Kaffiyeh
F
19

Simple Object

function foo(x) {
  // Function with other context
  // Modify `x` property, increasing the value
  x.value++;
}

// Initialize `ref` as object
var ref = {
  // The `value` is inside `ref` variable object
  // The initial value is `1`
  value: 1
};

// Call function with object value
foo(ref);
// Call function with object value again
foo(ref);

console.log(ref.value); // Prints "3"

Custom Object

Object rvar

/**
 * Aux function to create by-references variables
 */
function rvar(name, value, context) {
  // If `this` is a `rvar` instance
  if (this instanceof rvar) {
    // Inside `rvar` context...

    // Internal object value
    this.value = value;

    // Object `name` property
    Object.defineProperty(this, 'name', { value: name });

    // Object `hasValue` property
    Object.defineProperty(this, 'hasValue', {
      get: function () {
        // If the internal object value is not `undefined`
        return this.value !== undefined;
      }
    });

    // Copy value constructor for type-check
    if ((value !== undefined) && (value !== null)) {
      this.constructor = value.constructor;
    }

    // To String method
    this.toString = function () {
      // Convert the internal value to string
      return this.value + '';
    };
  } else {
    // Outside `rvar` context...

    // Initialice `rvar` object
    if (!rvar.refs) {
      rvar.refs = {};
    }

    // Initialize context if it is not defined
    if (!context) {
      context = this;
    }

    // Store variable
    rvar.refs[name] = new rvar(name, value, context);

    // Define variable at context
    Object.defineProperty(context, name, {
      // Getter
      get: function () { return rvar.refs[name]; },
      // Setter
      set: function (v) { rvar.refs[name].value = v; },
      // Can be overrided?
      configurable: true
    });

    // Return object reference
    return context[name];
  }
}

// Variable Declaration

// Declare `test_ref` variable
rvar('test_ref_1');

// Assign value `5`
test_ref_1 = 5;
// Or
test_ref_1.value = 5;

// Or declare and initialize with `5`:
rvar('test_ref_2', 5);

// ------------------------------
// Test Code

// Test Function
function Fn1(v) { v.value = 100; }

// Test
function test(fn) { console.log(fn.toString()); console.info(fn()); }

// Declare
rvar('test_ref_number');

// First assign
test_ref_number = 5;
test(() => test_ref_number.value === 5);

// Call function with reference
Fn1(test_ref_number);
test(() => test_ref_number.value === 100);

// Increase value
test_ref_number++;
test(() => test_ref_number.value === 101);

// Update value
test_ref_number = test_ref_number - 10;
test(() => test_ref_number.value === 91);
Foretop answered 31/1, 2014 at 18:13 Comment(3)
Your example seems to make some assumptions that you do not state. When I run it in an online JavaScript interpreter, I get an error: /workspace/Main.js:43 context = window; ReferenceError: window is not definedDiplomat
@Ant_222 Code fixed.Foretop
Thanks for the fix. Now it works, but I feel chary of voting for your answer because professional JavaScript programmers that I consulted consider your solution an abomination. I myself realise that it is rather dangerous in that in makes variables not what they seem to be. Nevertheless, your rvar solution doubtless has educational value.Diplomat
F
6

Yet another approach to pass any (local, primitive) variables by reference is by wrapping variable with closure "on the fly" by eval. This also works with "use strict". (Note: be aware that eval is not friendly to JavaScript optimizers, and also missing quotes around variable name may cause unpredictive results)

"use strict"

// Return text that will reference variable by name (by capturing that variable to closure)
function byRef(varName){
    return "({get value(){return "+varName+";}, set value(v){"+varName+"=v;}})";
}

// Demo

// Assign argument by reference
function modifyArgument(argRef, multiplier){
    argRef.value = argRef.value * multiplier;
}

(function(){
    var x = 10;

    alert("x before: " + x);
    modifyArgument(eval(byRef("x")), 42);
    alert("x after: " + x);
})()

Live sample: https://jsfiddle.net/t3k4403w/

Frauenfeld answered 16/1, 2017 at 9:52 Comment(1)
Good idea, but I decided against it because for output-only variables passing an arrow function x=>value=x is actually shorter, whereas bidirectional input-output parameters are not so often required. See my answer to a duplicate question for another eval-based approach, where you pass variable names and evaluate the result of the entire function.Diplomat
M
5

I personally dislike the "pass by reference" functionality offered by various programming languages. Perhaps that's because I am just discovering the concepts of functional programming, but I always get goosebumps when I see functions that cause side effects (like manipulating parameters passed by reference). I personally strongly embrace the "single responsibility" principle.

IMHO, a function should return just one result/value using the return keyword. Instead of modifying a parameter/argument, I would just return the modified parameter/argument value and leave any desired reassignments up to the calling code.

But sometimes (hopefully very rarely), it is necessary to return two or more result values from the same function. In that case, I would opt to include all those resulting values in a single structure or object. Again, processing any reassignments should be up to the calling code.

Example:

Suppose passing parameters would be supported by using a special keyword like 'ref' in the argument list. My code might look something like this:

//The Function
function doSomething(ref value) {
    value = "Bar";
}

//The Calling Code
var value = "Foo";
doSomething(value);
console.log(value); //Bar

Instead, I would actually prefer to do something like this:

//The Function
function doSomething(value) {
    value = "Bar";
    return value;
}

//The Calling Code:
var value = "Foo";
value = doSomething(value); //Reassignment
console.log(value); //Bar

When I would need to write a function that returns multiple values, I would not use parameters passed by reference either. So I would avoid code like this:

//The Function
function doSomething(ref value) {
    value = "Bar";

    //Do other work
    var otherValue = "Something else";

    return otherValue;
}

//The Calling Code
var value = "Foo";
var otherValue = doSomething(value);
console.log(value); //Bar
console.log(otherValue); //Something else

Instead, I would actually prefer to return both new values inside an object, like this:

//The Function
function doSomething(value) {
    value = "Bar";

    //Do more work
    var otherValue = "Something else";

    return {
        value: value,
        otherValue: otherValue
    };
}

//The Calling Code:
var value = "Foo";
var result = doSomething(value);
value = result.value; //Reassignment
console.log(value); //Bar
console.log(result.otherValue);

These code examples are quite simplified, but it roughly demonstrates how I personally would handle such stuff. It helps me to keep various responsibilities in the correct place.

Happy coding. :)

Morette answered 22/4, 2018 at 19:50 Comment(4)
Assigning and reassigning stuff (without any type-checking too) is what gives me goosebumps. As for responsibility, I expect doSomething(), to do that thing, not do that thing plus make an object plus and assign my variables to properties. Say I have an array which needs to be searched.I'd like the matching items placed in a second array and I want to know how many were found. A standard solution would be to call a function like this: 'var foundArray; if ((findStuff(inArray, &foundArray)) > 1) { // process foundArray}'. Nowhere in that scenario is a new, unknown object desirable or needed.Fleabag
@ElisevanLooij In your example case, I would prefer to have findStuff simply return the resulting array. You too have to declare a foundArray variable, so I would directly assign the resulting array to it: var foundArray = findStuff(inArray); if (foundArray.length > 0) { /* process foundArray */ }. This would 1) make the calling code more readable/understandable, and 2) considerably simplify the internal functionality (and thus also the testability) of the findStuff method, making it actually a lot more flexible in different (re)use-cases / scenarios.Morette
@ElisevanLooij However, I do agree that reassignments (like in my answer) are indeed a "code smell" and I would actually want to avoid those as much as possible as well. I will think about editing (or even reformulating) my answer in such a way that it will better reflect my actual opinion on the subject. Thanks for your reaction. :)Morette
Great answer. Helped me with what I needed, thanks. Was wanting to avoid passing a variable by string and passing its context (for automatic reassignment), and was missing the otherwise obvious "just assign it then and there" (duh).Hagar
C
4

I've been playing around with syntax to do this sort of thing, but it requires some helpers that are a little unusual. It starts with not using 'var' at all, but a simple 'DECLARE' helper that creates a local variable and defines a scope for it via an anonymous callback. By controlling how variables are declared, we can choose to wrap them into objects so that they can always be passed by reference, essentially. This is similar to one of the Eduardo Cuomo's answer above, but the solution below does not require using strings as variable identifiers. Here's some minimal code to show the concept.

function Wrapper(val){
    this.VAL = val;
}
Wrapper.prototype.toString = function(){
    return this.VAL.toString();
}

function DECLARE(val, callback){
    var valWrapped = new Wrapper(val);    
    callback(valWrapped);
}

function INC(ref){
    if(ref && ref.hasOwnProperty('VAL')){
        ref.VAL++; 
    }
    else{
        ref++;//or maybe throw here instead?
    }

    return ref;
}

DECLARE(5, function(five){ //consider this line the same as 'let five = 5'
console.log("five is now " + five);
INC(five); // increment
console.log("five is incremented to " + five);
});
Clubfoot answered 14/5, 2014 at 18:47 Comment(1)
The problem with this approach is that it's not actually an equivalent to let five = 5;, because it's not setting the variable in the outer context, it is only usable inside the function. That's why you don't need to use a string. Still, upvoted for the novel idea of using a closure for the sole purpose of making a reference, and storing and localizing the value within that reference. Though, this could just be done with a class or an object instead. Then you could store the reference object and use it for more generic purposes than just INC(ref). Doing this for a project of mine.Hagar
T
4

There's actually a pretty sollution:

function updateArray(context, targetName, callback) {
    context[targetName] = context[targetName].map(callback);
}

var myArray = ['a', 'b', 'c'];
updateArray(this, 'myArray', item => {return '_' + item});

console.log(myArray); //(3) ["_a", "_b", "_c"]
Torero answered 15/7, 2017 at 0:59 Comment(1)
In what way is it pretty?Emery
R
2

Actually it is really easy. The problem is understanding that once passing classic arguments, you are scoped into another, read-only zone.

The solution is to pass the arguments using JavaScript's object-oriented design. It is the same as putting the arguments in a global/scoped variable, but better...

function action(){
  /* Process this.arg, modification allowed */
}

action.arg = [["empty-array"], "some string", 0x100, "last argument"];
action();

You can also promise stuff up to enjoy the well-known chain: Here is the whole thing, with promise-like structure

function action(){
  /* Process this.arg, modification allowed */
  this.arg = ["a", "b"];
}

action.setArg = function(){this.arg = arguments; return this;}

action.setArg(["empty-array"], "some string", 0x100, "last argument")()

Or better yet...

action.setArg(["empty-array"],"some string",0x100,"last argument").call()
Rosas answered 4/5, 2015 at 21:36 Comment(2)
this.arg only works with action instance. This does not work.Foretop
@EduardoCuomo You can simply use a class instead to solve that problem. I've found that the this keyword is the main functionality-providing purpose for class in JS.Hagar
E
2

JavaScript can modify array items inside a function (it is passed as a reference to the object/array).

function makeAllPretty(items) {
   for (var x = 0; x < myArray.length; x++){
      // Do stuff to the array
      items[x] = makePretty(items[x]);
   }
}

myArray = new Array(var1, var2, var3);
makeAllPretty(myArray);

Here's another example:

function inc(items) {
  for (let i=0; i < items.length; i++) {
    items[i]++;
  }
}

let values = [1,2,3];
inc(values);
console.log(values);
// Prints [2,3,4]
Enrich answered 28/10, 2018 at 20:59 Comment(0)
S
2

As we don't have pass by reference functionality in JavaScript, the only way to do this is to make the function return the value and let the caller assign it:

So

makePretty(myArray[x]);

should be

myArray[x] = makePretty(myArray[x]);

This is in case you need assignment inside the function, if only mutation is necessary, then passing the object and mutating it should be enough

Sosa answered 6/7, 2021 at 10:23 Comment(1)
This is also almost always a better design, unless there are demonstrable performance issues with it: functional, stateless design generates less complexity. If the caller wants to use the result to mutate something, that's their call, but the function has no business mandating it.Socinus
J
1

Putting aside the pass-by-reference discussion, those still looking for a solution to the stated question could use:

const myArray = new Array(var1, var2, var3);
myArray.forEach(var => var = makePretty(var));
Juliajulian answered 14/7, 2019 at 19:25 Comment(1)
What is the explanation? How is it different/better from other answers?Emery
I
0

I know exactly what you mean. The same thing in Swift will be no problem. The bottom line is use let, not var.

The fact that primitives are passed by value, but the fact that the value of var i at the point of iteration is not copied into the anonymous function is quite surprising to say the least.

for (let i = 0; i < boxArray.length; i++) {
  boxArray[i].onclick = function() { console.log(i) }; // Correctly prints the index
}
Insouciance answered 23/5, 2018 at 0:19 Comment(0)
V
0

I like to solve the lack of by reference in JavaScript like this example shows.

The essence of this is that you don't try to create a by reference. You instead use the return functionality and make it able to return multiple values. So there isn't any need to insert your values in arrays or objects.

var x = "First";
var y = "Second";
var z = "Third";

log('Before call:',x,y,z);
with (myFunc(x, y, z)) {x = a; y = b; z = c;} // <-- Way to call it
log('After call :',x,y,z);


function myFunc(a, b, c) {
  a = "Changed first parameter";
  b = "Changed second parameter";
  c = "Changed third parameter";
  return {a:a, b:b, c:c}; // <-- Return multiple values
}

function log(txt,p1,p2,p3) {
  document.getElementById('msg').innerHTML += txt + '<br>' + p1 + '<br>' + p2 + '<br>' + p3 + '<br><br>'
}
<div id='msg'></div>
Vasileior answered 27/7, 2020 at 15:39 Comment(2)
This approach requires a whole lot of identifiers and assignments for a basic, fundamental problem, and it doesn't address the situations where one would explicitly need a reference in order to solve their problem. Some examples would include creating new properties on or deleting properties from the reference, passing the reference around to a great many functions, changing the type or swapping out the reference for something else altogether, etc. The ideal solution(s) to this problem in JS world are thus going to involve the Flyweight pattern with one variety of object or another.Hagar
This approach was sort of discussed here. Also, when passing variables in JS objects, there's no need to do { a: a, b: b, c: c }, etc., you can just do { a, b, c }. Lastly, you can use Destructuring Assignment on the function call line and have no need to use with. (If you do use with, it's recommended to just use scope brackets {} instead.)Hagar
V
0

If you want to pass variables by reference, a better way to do that is by passing your arguments in an object and then start changing the value by using window:

window["varName"] = value;

Example:

// Variables with first values
var x = 1, b = 0, f = 15;


function asByReference (
    argumentHasVars = {},   // Passing variables in object
    newValues = [])         // Pass new values in array
{
    let VarsNames = [];

    // Getting variables names one by one
    for(let name in argumentHasVars)
        VarsNames.push(name);

    // Accessing variables by using window one by one
    for(let i = 0; i < VarsNames.length; i += 1)
        window[VarsNames[i]] = newValues[i]; // Set new value
}

console.log(x, b, f); // Output with first values

asByReference({x, b, f}, [5, 5, 5]); // Passing as by reference

console.log(x, b, f); // Output after changing values
Verney answered 7/8, 2020 at 16:13 Comment(2)
But window is the global (aliased?) object(?) (in a web browser context). So effectively passing back information in global variables(?).Emery
@PeterMortensen That is why I like the answer suggesting to simply manually assign/reassign the variable inline, in whatever context it's being used in. However, if one wanted, they could also pass the context/namespace/object in which they want the variable to exist, with globalThis being the default value (avoiding web-browser-only issues), although that approach unfortunately requires that the variable name be passed in as a string.Hagar
R
0

Using Destructuring here is an example where I have 3 variables, and on each I do the multiple operations:

  • If value is less than 0 then change to 0,
  • If greater than 255 then change to 1,
  • Otherwise dived the number by 255 to convert from a range of 0-255 to a range of 0-1.
let a = 52.4, b = -25.1, c = 534.5;
[a, b, c] = [a, b, c].map(n => n < 0 ? 0 : n > 255 ? 1 : n / 255);
console.log(a, b, c); // 0.20549019607843136 0 1
Rapine answered 3/3, 2021 at 19:9 Comment(1)
This does not "mutate" original number values, instead destructuring shadows original variable with a new reference.Transpicuous
S
0

This might not answer the exact question as stated, but for many cases where topic comes up, a more functional design is a fruitful avenue that actually reduces complexity in stead of adding it:

result = new Array(var1, var2, var3)
    .map(makePretty)
Socinus answered 20/11, 2023 at 8:27 Comment(1)
I kept the naming from the question, but following the mantra "verbs are for side effects", the applied transform would be better named just "pretty"Socinus
N
0

Let's be simple!!

It does not require this much code to provide the proper answer to your question.

  1. when you call makePretty(myArray[x]); nobody can tell it passes by reference or passes by value.
  2. Because you don't have specified the data type of the 'x'th ELEMENT of myArray.
  3. If that element is a int (or any data type passes by value) it will pass by the value to the function makePretty.
  4. If that element is a pass by reference type it will pass by reference.
  5. Of course your myArray is reference type.
  6. But I'm talking here about the data type of the element. Not the whole array.
Nataline answered 23/2 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.