2

I am new to Javascript (and programming in general) and have been searching for a way to change the value of an arbitrary number of aguments using a Javascript function.

The answer here (JavaScript variable number of arguments to function) was quite helpful. I was able to use it to create the two of the functions I need, but I'm having trouble with the third.

Basically I would like to pass a variable number of objects (primitive or more complex) into a function and have the function change the value of each object.

var pants = true;
var house = true;
var hair = {/* lots of stuff */};

var onFire = function() {
        for (var i = 0; i < arguments.length; i++) {
            arguments[i] = false;
        }
};

onFire(pants, house, hair);

Console outputs:

>pants;
 true

>house;
 true

>hair;
 Object

How can I formulate this function so the the result is:

>pants;
 false

>house;
 false

>hair;
 false

Any help would be greatly appreciated!

Edit:

To clarify things - I am trying to create a reusable helper function that changes the value of any object passed in to false instead of typing:

var a1 = false;
var a2 = false;
...
var a+n = false;

If I use mathec's method - is it possible to 'parse' object so that it's properties overwrite the global variables of the same name, or am I stuck with typing it out explicitly each time?

var object = {
    pants: {/* lots of stuff */},
    house: {/* lots of stuff */},
    hair: {/* lots of stuff */}
};

function modifyObject(obj) {
    obj.pants = false;
    obj.house = false;
    obj.hair = false;
}

function someMagic(object){
    // wand waves...
    // rabbit exits hat....
}

Console Output:

>pants;
 false

>house;
 false

>hair;
 false 
Community
  • 1
  • 1
TiLogic
  • 199
  • 1
  • 2
  • 10

5 Answers5

5

When you pass variables in JavaScript you're passing a copy of a reference to a value if it's an object, but if it's a primitive (like a true/false) you're copying the actual value. This basically means, if you pass in an object and modify one of the object's properties, you'll be modifying the original object. But if you pass in a primitive like true/false, you'll just be modifying the copy, and not the original value. So if your goal is to modify the original values, one option is to store those values in an object and pass in the object instead. For example:

var object = {
    pants: true,
    house: true,
    hair: {}
};

function modifyObject(obj) {
    obj.pants = true;
    obj.house = true;
    obj.hair = true;
}

If you want to modify an arbitrary number of arguments, just remember that if you're passing in true/false you're copying those values. So if you change them inside the function you won't be modifying the original values.

A quick way to remember this is if you ever pass an object or an array, you're modifying the actual object. Anything else, you're modifying a copy.

Edit

So interpreting what you want to do literally, you could write this:

var a = true,
    b = true;

/* pass in variable names */
function makeFalse() {
   var i, len;

   for (i = 0, len = arguments.length; i < len; ++i) {
     window[arguments[i]] = false;
   }
 }

 makeFalse("a", "b");

But I can't think of a good reason to do this :-). I would use configuration objects to store flags and state variables, not global variables.

cmather
  • 1,950
  • 14
  • 17
  • 1
    good explanation, with the one exception that modifying the object variable itself wont do anything, but modifying its properties will. – Thomas Jones May 11 '12 at 02:17
  • Thanks for the clarification! I found a good way to think about it is that variable labels or names are separate from the values that they point to. The variable names are always separate in the function. If you reassign the variable inside the function you're just reassigning that local variable. – cmather May 11 '12 at 02:20
  • I might be able to give some other patterns you can use if you could maybe give an example? It sounds like you're trying to initialize an object with properties, but not sure yet. – cmather May 11 '12 at 05:34
  • ….my goal is to avoid typing out var a_1 = false, var a_2 = false … var a_n = false. If I use the method in your example is there a way to parse 'object' after it's value is changed by 'modifyObject()' so that the modified 'hair' overwrites the the original 'hair' object? – TiLogic May 11 '12 at 05:39
  • I'm taking your example a bit literally, but if you want all variables to be initially false you don't have to initialize them to anything. Because 'undefined' is what all variables start off as, and undefined evaluates to 'false' in if-statements. So... var a_1; if(a_1) will be false. This is a bit of a guess to what you're trying to do, so sorry if it's way off. Another way to initialize objects is to use constructor functions. I can give some examples of its helpful. – cmather May 11 '12 at 06:49
  • Sorry, I guess my question wasn't stated clearly enough... The objects are already initialized. My goal is to mark with a 'flag' so they can be safely ignored by the other parts of my script. I chose false, because it was a primitive and somewhat descriptive but null would work just as well. – TiLogic May 11 '12 at 16:16
  • I've edited my question to make things more clear (hopefully!). – TiLogic May 11 '12 at 16:26
  • I've never seen this pattern before so not sure why it would be used, but you could do this. I'll edit my above post. – cmather May 11 '12 at 17:00
1

Unfortunately, this is not directly possible.

Javascript is a pass-by-value language, and in the case of object types, its a pass by value by reference (at least thats how Ive seen it referred to)

Is JavaScript a pass-by-reference or pass-by-value language?

goes pretty in depth to it, and https://stackoverflow.com/a/3638034/1093982 in particular has a great answer.

here is a jsfiddle demonstrating the example in the above answer:

http://jsfiddle.net/hjPHJ/

note how anything assigning to a parameter is not carried into the scope above.

Community
  • 1
  • 1
Thomas Jones
  • 4,892
  • 26
  • 34
0

You could try JavaScript's typeof() function, which should return "object", and then treat it differently in your code. As for changing the value of an object, I think you actually want to change the value of a property, but I am not sure I understand your question well enough.

To change an object property, you would do something like this.

hair.color = 'red';

If you want to unset the object, you can do this.

delete window.some_var; 
  • I was focusing on objects. As mathec noted, you cannot change the primitive variables this way, but you could pass them as a single object. – Lawrence H. May 11 '12 at 02:17
0

Javascript passes each argument as a reference by value, so when you change the value of a passed in reference it modifies the copied value.

However it does have something else which is very powerful and thats closure. In your example onFire already has access to pants, house, and hair through the closure scope and can modify them directly.

Abdullah Jibaly
  • 53,220
  • 42
  • 124
  • 197
0

When you call a function in javascript, you are passing values and not references to the original object. There are a couple of ways that you can do what you want, but not directly by passing each value to change to the function.

First you can pass an array:

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

arr = [true, true, {}];
onFire(arr); // arr[0] through arr[2] are now false

Another would be to pass an object, whose properties can be modified, you just can't change the value of the variable you pass as an argument:

function onFire(obj) {
    obj.pants = false;
    obj.house = false;
    obj.hair = false;
}

onFire( { pants: true, house: true, hair: { } } );
// obj.pants, obj.house and obj.hair are now false

Neither of these accomplishes just what you want, but if I knew the reason for doing what you are asking there might be a better way...

Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113