Search code examples
javascript

Different ways of passing a variable by reference?


I want to pass a variable to a function and have the function change the value.

I know I can do this as an object but am wondering if there is some way to do this that I haven't thought of.

This is what I want to do, but it doesn't work the way I want of course:

function test1(vari) {
    vari = 2;
}
var myvar1 = 1;
test1(myvar1);
console.log(myvar1); //1

This works, but I don't really want to make all the variables objects:

function test2(vari) {
    vari.val = 2;
}
var myvar2 = { val: 1 };
test2(myvar2);
console.log(myvar2.val); //2

This also works, but not an acceptable solution:

function test3(vari) {
    eval(vari + ' = 2;');
}
var myvar3 = 1;
test3('myvar3');
console.log(myvar3); //2

Is there a better option than these?

Updated

A better example of what I would like to do:

function test5(vari, onblur) {
    document.querySelector('body').innerHTML += `<input id="ctl_${vari}" type="text" value="${vari}">`;
    el = document.getElementById(`ctl_${vari}`);
    el.addEventListener('blur', function(e) {
        vari = e.target.value; //Doesn't update original variable
        onblur(e);
    });
    return el;
}
var myvar5 = 'test';
var ele = test5(
    myvar5,
    function(e) {
        //Could set myvar5 = e.target.value but not wanting to do this for every single field
        console.log(myvar5);
    }
);

Solution

  • Like already stated in the comments, you cannot pass-by-reference in JavaScript. All arguments passed to a function are pass-by-value. This is even the case for objects. Though you can mutate an object passed as argument, you cannot re-assign it (making it pass-by-value). See: Is JavaScript a pass-by-reference or pass-by-value language? and Is Java "pass-by-reference" or "pass-by-value"? (also applies to JavaScript) for details.

    What you can do is return multiple values using an array:

    function test(a, b) {
      return [a + b, a - b];
    }
    
    let a = 5, b = 2;
    [a, b] = test(a, b);
    

    The final value for a is 7 and b is 3.

    Note that the semicolon after let a = 5, b = 2; is required, otherwise it's executed as let a = 5, b = 2[a, b] = test(a, b); Which in this case results in "Uncaught ReferenceError: can't access lexical declaration 'b' before initialization".

    However in your specific scenario you could simply pass the desired value to the onblur function as an argument to avoid myvar5 = e.target.value in every function definition.

    function test5(vari, onblur) {
        document.querySelector('body').innerHTML += `<input id="ctl_${vari}" type="text" value="${vari}">`;
        const el = document.getElementById(`ctl_${vari}`);
        el.addEventListener('blur', function(e) {
            onblur(e, e.target.value);
        });
        return el;
    }
    
    // best matching the question code
    var myvar5 = 'test';
    var ele = test5(myvar5, function(e, myvar5) {
        console.log(myvar5);
    });
    
    // probably preferable given the current question code
    var ele = test5('test', function(e, value) {
        console.log(value);
    });