tags:

views:

75

answers:

4

Hi there,

I know that it is bad practice to write code like this:

var createBox = function(width, height, margin){
    alert("Margin is set to " + margin);
    //margin is undefined in this context or why?
    var margin = margin || 2;
    alert("Margin is now " + margin);
}
createBox(0,0,0);

But can someone please explain, why margin is always set to 2?

Is it because it is undefined in the direct context of initializing a variable with the same name inside the function?

edit: sorry, I got the problem wrong ...

Please give a small hint :) Regards, Tom

+3  A: 

The || operator in JavaScript returns the value of the first operand if the first operand is truthy. Otherwise it returns the value of the second operand. It doesn't return 1/0, or true/false, as in some other languages.

Therefore when the margin argument holds a falsy value, such as 0 or undefined, it will return 2, since these are both falsy values in JavaScript.

The falsy values in JavaScript are: an empty string "", the null value, a value of 0, the NaN value, the boolean value false, and also undefined.

What you describe is a very common idiom in JavaScript. In fact the || operator is sometimes called the default operator1. You can use it to assign default values to variables when they are undefined. The problem in this case is that since 0 is a valid argument, the default operator is not behaving as required. You may want to do the following instead:

margin = typeof margin === 'undefined' ? 2 : margin;

1 Douglas Crockford: The Elements of JavaScript Style - Part 2 - Idioms.

Daniel Vassallo
Yes Daniel, but why is margin undefined? if I use f.e. var margin2 = margin || false; margin2 is set to 0 as expected
shapeshifta
@shapeshifta: Updated my answer... `margin` is not undefined. It is set to `0`, which is also a "falsy" in JavaScript. Therefore, the `||` operator returns the second operand: `2` and assigns it to `margin`.
Daniel Vassallo
I think you are right in a way, but that is not the answer for my problem I think. Just compare: var margin = margin || 2 //2; var margin2 = margin || 2; //0 -> this is my question :)
shapeshifta
@shapeshifta it is the answer to your problem.
Pointy
to much coffee, to little sleep ... sorry!
shapeshifta
+3  A: 

If you call createBox(0,0,0), then margin is 0 (which has the truth value of false), so the expression margin || 2 becomes 0 || 2 which is equal to 2.

Kos
but if I write var margin2 = margin || 2, margin2 is set to 0 as expected ;)
shapeshifta
@shapeshifta no it is not set to 2. That definitely will not happen if margin is zero.
Pointy
Not for me. `margin2` outputs 2 on the last alert.
Louis
Oh I am so sorry, I mixed it up ... :(
shapeshifta
+2  A: 

0 evaluates to false List of Truthy Values

epascarello
+1  A: 
// This function creates a new box by receiving three parameters
var createBox = function(width, height, margin){
    // Output the margin of the box, zero in current case
    alert("Margin is set to " + margin);
    // If the margin is zero or undefined, '' set default value to 2
    var margin = margin || 2;
    // Output the new value of the margin which is 2
    alert("Margin is now " + margin);
}
// here will show Margin: 0 after that Margin: 2
createBox(0,0,0);

// here will show Margin: 1 after that Margin: 1
createBox(0,0,1);

// here will show Margin: 3 after that Margin: 3
createBox(1,2,3);
infinity