90

Can we pass a reference of a variable that is immutable as argument in a function?

Example:

var x = 0;
function a(x)
{
    x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
Jaak Kütt
  • 2,566
  • 4
  • 31
  • 39
user1342369
  • 1,041
  • 2
  • 9
  • 9
  • Arguable this is bad style as you are intending to use side-effects of a function to cause mutation. This can make your code harder to follow. – spex Sep 18 '17 at 12:04

15 Answers15

157

Since JavaScript does not support passing parameters by reference, you'll need to make the variable an object instead:

var x = {Value: 0};

function a(obj)
{
    obj.Value++;
}

a(x);
document.write(x.Value); //Here i want to have 1 instead of 0

In this case, x is a reference to an object. When x is passed to the function a, that reference is copied over to obj. Thus, obj and x refer to the same thing in memory. Changing the Value property of obj affects the Value property of x.

Javascript will always pass function parameters by value. That's simply a specification of the language. You could create x in a scope local to both functions, and not pass the variable at all.

Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
  • Is there a way of doing it so another person will just do : var x=0;a(x); and that the function set an object with the value of x ? (or something like that) – user1342369 Apr 19 '12 at 16:02
  • 8
    Hey, thanks for introducing me to [code snippets on SO](http://meta.stackoverflow.com/q/269753/1256925). Hadn't heard of them before I saw it used in your answer. – Joeytje50 Nov 20 '14 at 11:28
  • @Joeytje50 - Yup, [this feature](http://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) was just added back in September. Very handy! – Mike Christensen Nov 20 '14 at 16:43
  • What if you don't know the name for the obj property for example if it was obj.name then next time you want to update obj.surname ? How can you make a function adapt to that kind of flexibility? – Sir Oct 10 '15 at 05:18
  • 1
    @Dave this may be a late answer but you can make your function expect for 3 parameters, the obj, the property name and the value. Remember you can access a property of an object by doing obj.propertyname or obj['propertyname'] which will be the way you want when you want flexibility. Pass 3 parameters and do obj['propertyname'] = value and that will be reusable. – Carlos Calla Feb 01 '16 at 15:31
  • "Since JavaScript does not support passing parameters by reference, you'll need to make the variable an object instead". I think it is more correct to say that since JavaScript does not give you control over which values are passed by reference, you can abuse its inconsistency by wrapping your variable in an object, which is always passed by reference. – Basic Block Aug 08 '17 at 07:30
  • @Stuffe - In JavaScript, nothing is passed by reference. Everything is passed by value. – Mike Christensen Aug 08 '17 at 20:49
19

This question may help: How to pass variable by reference in javascript? Read data from ActiveX function which returns more than one value

To summarise, Javascript primitive types are always passed by value, whereas the values inside objects are passed by reference (thanks to commenters for pointing out my oversight). So to get round this, you have to put your integer inside an object:

var myobj = {x:0};

function a(obj)
{
    obj.x++;
}

a(myobj);
alert(myobj.x); // returns 1

  
Community
  • 1
  • 1
n00dle
  • 5,949
  • 2
  • 35
  • 48
  • 3
    Object variables are always passed by value as well -- it's just that *the value is a reference* to an object. There's a difference between *passing by reference* and *passing a reference by value*. Namely, when you pass `x` by value, whether `x` is an object or not, you can't replace it with a whole other value in any way the caller will see. – cHao Apr 19 '12 at 17:31
  • *whereas objects are passed by reference* is simply not true. Nothing in JavaScript is passed by reference. – Mike Christensen Oct 31 '13 at 00:33
  • If you pass a primate type by value (is referenced to by x), why does x not change after, unless you pass the object – SuperUberDuper Feb 09 '17 at 09:32
14

I have found a slightly different way implement pointers that is perhaps more general and easier to understand from a C perspective (and thus fits more into the format of the users example).

In JavaScript, like in C, array variables are actually just pointers to the array, so you can use an array as exactly the same as declaring a pointer. This way, all pointers in your code can be used the same way, despite what you named the variable in the original object.

It also allows one to use two different notations referring to the address of the pointer and what is at the address of the pointer.

Here is an example (I use the underscore to denote a pointer):

var _x = [ 10 ];

function foo(_a){
    _a[0] += 10;
}

foo(_x);

console.log(_x[0]);

Yields

output: 20
William Oliver
  • 1,412
  • 4
  • 24
  • 35
8

You refer to 'x' from window object

var x = 0;

function a(key, ref) {
    ref = ref || window;  // object reference - default window
    ref[key]++;
}

a('x');                   // string
alert(x);
AlexisK
  • 111
  • 1
  • 2
4

Late answer but I have come across a way of passing primitive values by reference by means of closures. It is rather complicated to create a pointer, but it works.

function ptr(get, set) {
    return { get: get, set: set };
}

function helloWorld(namePtr) {
    console.log(namePtr.get());
    namePtr.set('jack');
    console.log(namePtr.get())
}

var myName = 'joe';
var myNamePtr = ptr(
    function () { return myName; },
    function (value) { myName = value; }
);

helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack

In ES6, the code can be shortened to use lambda expressions:

function ptr(get, set) {
    return { get: get, set: set };
}

function helloWorld(namePtr) {
    console.log(namePtr.get());
    namePtr.set('jack');
    console.log(namePtr.get())
}

var myName = 'joe';
var myNamePtr = ptr(() => myName, v => myName = v);

helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack
Himanshu
  • 399
  • 3
  • 14
3

Javascript should just put pointers into the mix coz it solves a lot of problems. It means code can refer to an unknown variable name or variables that were created dynamically. It also makes modular coding and injection easy.

This is what i see as the closest you can come to c pointers in practice

in js:

var a = 78;       // creates a var with integer value of 78 
var pointer = 'a' // note it is a string representation of the var name
eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12

in c:

int a = 78;       // creates a var with integer value of 78 
int pointer = &a; // makes pointer  to refer to the same address mem as a
*pointer = 12;   // changes the value of a to 12
Emmanuel Mahuni
  • 1,766
  • 16
  • 16
1

In JavaScript that would be a global. However, your function would look more like this:

function a(){
   x++;
};

Since x is in the global context, you don't need to pass it into the function.

Community
  • 1
  • 1
Maess
  • 4,118
  • 20
  • 29
  • 1
    Valid point, though I'd point out the variable doesn't need to be global (and many would advise against doing this ever), it simply needs to be in the same scope as the caller and the callee. – Mike Christensen Apr 19 '12 at 15:58
1

It might be impossible since JavaScript doesn't have Perl's "" operator to get a primitive by reference, but there is a way to create an "effectively a pointer" object for a primitive using this pattern.

This solution makes the most sense for when you already have the primitive(so you can't put it into an object anymore without needing to modify other code), but still need to pass a pointer to it for other parts of your code to tinker with its state; so you can still tinker with its state using the seamless proxy which behaves like a pointer.

var proxyContainer = {};

// | attaches a pointer-lookalike getter/setter pair
// | to the container object.
var connect = function(container) {
    // | primitive, can't create a reference to it anymore
    var cant_touch_this = 1337;
    
    // | we know where to bind our accessor/mutator
    // | so we can bind the pair to effectively behave
    // | like a pointer in most common use cases.
    Object.defineProperty(container, 'cant_touch_this', {
        'get': function() {
            return cant_touch_this;
        },
        'set': function(val) {
            cant_touch_this = val;
        }
    });
};

// | not quite direct, but still "touchable"
var f = function(x) {
    x.cant_touch_this += 1;
};

connect(proxyContainer);

// | looks like we're just getting cant_touch_this
// | but we're actually calling the accessor.
console.log(proxyContainer.cant_touch_this);

// | looks like we're touching cant_touch_this
// | but we're actually calling the mutator.
proxyContainer.cant_touch_this = 90;

// | looks like we touched cant_touch_this
// | but we actually called a mutator which touched it for us.
console.log(proxyContainer.cant_touch_this);

f(proxyContainer);

// | we kinda did it! :)
console.log(proxyContainer.cant_touch_this);
Dmytro
  • 5,068
  • 4
  • 39
  • 50
0

In JavaScript, you cannot pass variables by reference to a function. However you can pass an object by reference.

d4rkpr1nc3
  • 1,817
  • 13
  • 16
  • 3
    Simply not true. You cannot pass anything by reference in JavaScript. – Mike Christensen Oct 31 '13 at 00:33
  • 1
    The object reference is passed as value, so everything is passed as value. – Carlos Calla Feb 01 '16 at 15:49
  • interesting observation; it seems to be IMPOSSIBLE to create a reference to an existing primitive in JavaScript; once a primitive is bound, any changes to this primitive can never be noticed by its naive referants because the referants point to the value that the variable, which happens to be a primitive; so the only way to "point" to a primitive is if the primitive is wrapped in a variable whose typeof is "Object"; as no other types can store a reference. TLDR; there is no Perl "\" operator in JavaScript; it's either a reference to begin with, or you can never point to it. – Dmytro Jan 29 '17 at 17:47
  • The annoying part of this is when you want to create a bag of shared state eg "window.shared" as a map of references to variables which are currently null/undefined which you will set later; in this case, as you set the values of the state which is currently null/undefined, the "window.shared" variable will not recognize the changes, even though they are stored in an Object type, it's already too late; the "null/undefined" values have to be inside Object types to begin with for this to work, eg [null] [undefined]. – Dmytro Jan 29 '17 at 17:50
  • That said, you can be clever and put in functions in such a global variable, which have a getter and setter for each of these not yet set variables, and these functions WILL dynamically find the CURRENT state of the primitive and get/set it, but it can't return a pointer to that variable(but can return a proxy that can effectively behave the same way as that variable and mutate it indirectly, using getters/setters). – Dmytro Jan 29 '17 at 17:52
0

I'm thinking that in contrary to C or any language with pointers :

/** Javascript **/
var o = {x:10,y:20};
var o2 = {z:50,w:200};
  • obviously in javascript you cannot access to objects o and o2 addresses in memory
  • but you can't compare their address neither : (no trivial possibility to sort them, and then access by dichotomy)

.

o == o2 // obviously false : not the same address in memory
o <= o2 // true !
o >= o2 // also true !!

that's a huge problem :

  • it means that you can list/manage every objects created (allocated) by your application,

  • from that huge list of objects, compute some information about these (how they are linked together for example)

  • but when you want to retrieve the information you created about a specific object, you cannot find it in your huge list by dichotomy : there is no unique identifier per object that could be used as a replacement of the real memory address

this finally means that this is a huge problem, if you want to write in javascript :

  • a javascript debugger / IDE
  • or a specially optimized garbage collector
  • a data structure drawer / analyzer
reuns
  • 854
  • 10
  • 14
0

JavaScript doesn't support passing primitive types by reference. There is a workaround, though.

Put all the variables you need to pass in an object. In this case, there's only one variable, x. Instead of passing the variable, pass the variable name as a string, which is "x".

var variables = {x:0};
function a(x)
{
    variables[x]++;
}
a("x");
alert(variables.x);
clickbait
  • 2,818
  • 1
  • 25
  • 61
0

Depending on what you would like to do, you could simply save the variable name, and then access it later on like so:

function toAccessMyVariable(variableName){
  alert(window[variableName]);
}

var myFavoriteNumber = 6; 

toAccessMyVariable("myFavoriteNumber");

To apply to your specific example, you could do something like this:

var x = 0;
var pointerToX = "x";

function a(variableName)
{
    window[variableName]++;
}
a(pointerToX);
alert(x); //Here I want to have 1 instead of 0
Lioness
  • 500
  • 8
  • 13
  • This only works in a browser environment and is specific to `window` object. Also, it is less recommended to use global variables, since there might already be a variable with the same name. – Yuna Aug 03 '18 at 13:52
0

It just doesn't support pointers, end of story :-(.

I would like to add that, while I'm brand new and coming from a C background, from what I'm reading about the event loop and stack, you should keep whichever object as close to its caller as possible. As I'm brand new, I could have this wrong.

A lot of answers here suggest to make it global, but again if I'm reading correctly, that could possibly increase the stack hops and in a way, possibly fragment your event loop needlessly (depending on what the called object is currently doing) .

Also, any example given that mimics pointers, is just 1 in many ways to do the same thing, which will not be a pointer.

  • In JS, it is often considered bad practice to make variables global. You should't really need to unless the variable will be heavily used that way. For instance, in a web app, the object representing the current user may be stored globally, however is advised against, as this exposes it to the developer tools and clutters the global namespace. Instead, it's best to use state managers, with global instances, which contain user objects. When fetching the values within objects, these are references, IE pointers. These behave like traditional C pointers, however, can't be allocated manually. – J-Cake Oct 29 '21 at 01:27
0

I'll agree with the most quotet answer, but please be aware from 'var' argument, use 'let', or better in this case 'const', because the pointer, or the pointing object shouldn`t be change anytime.

const x = {value: 0};

function foo(obj){
  ++obj.value;
}

foo(x);
alert(x.value);
-1

In your example you actually have 2 variables with the same name. The (global) variable x and the function scoped variable x. Interesting to see that javascript, when given a choice of what to do with 2 variables of the same name, goes with the function scoped name and ignores the out-of-scope variable.

It's probably not safe to presume javascript will always behave this way...

Cheers!

tpaytn
  • 1
  • This answer doesn't add any value to this post. @Mike Christensen's answer is more detailed and already accepted. – Alexander Jul 06 '15 at 23:09