Digging through the glMatrix-0.9.5.min.js source used in my webGL project and I came across several lines of code like this...
vec3.negate = function (a, b)
{
b || (b = a); // <-- What exactly does this line do?
b[0] = -a[0];
b[1] = -a[1];
b[2] = -a[2];
return b;
};
Not sure what that code is doing or even if it's a bug considering it's a third-party file, but I also know I'm not completely up to speed about JavaScript as a language. (For instance, I just learned about protocols because of this. Odd/interesting concept.)
So is that valid, and if so, what exactly is it doing?
My guess is it's shorthand for the following, saying 'If 'b' isn't set, set it to a'
if(!b)
{
b = a;
}
which can also just be written
if(!b) b = a;
which I'd argue is much more clear. But again, I'm guessing as to what that actually means/does. Could be wrong.
Follow-up:
Are these two if-conditions equal?
if(!b){ ... }
if(b == undefined){ ... }
I'm wondering if there's a complication between 'undefined' and a defined value that's 'null'
a better way to write that would be
b = b || a;
That means:
b = b ? b : a; //or
b = b || a;
This is shorthand for
if (!b) { b = a }
Lets break it down:
To the left of the || it is asserting on the truthiness of b http://james.padolsey.com/javascript/truthy-falsey/
If b is truthy, then the part to the right of the || will not be evaluated. If b is falsey, then b will get assigned the value/reference of a.
It's basically setting the value of b to a if b is undefined via the || operator which can be used as a null-coalescing operator in Javascript.
You could think of it in terms of an if-statement as follows :
if(b == undefined){
b = a;
}
A Matter of Preference
It's ultimately a matter of preference with regards to what makes the most sense, but any of the approaches that you'll find in this discussion are likely valid options :
// Explicitly using undefined in the comparison
if(b == undefined) { b = a }
// Using an if-statement (with a not)
if(!b){ b = a }
// Using a ternary operator
b = b ? || a
Regarding Your Follow-up
Follow-up: Are these two if-conditions equal?
if(!b){ ... }
if(b == undefined){ ... }
I'm wondering if there's a complication
between 'undefined' and a defined value that's 'null'
Yes, there can be differences as seen with an empty string, which would have the following results :
var b = '';
!b // true
b == undefined // false
Differentiating null and undefined values can be tricky and since it's a bit of out the scope of this question, you might consider checking out this related discussion on the topic, which commonly recommends the use of if(b == null) { b = a; } as opposed to checks against undefined.
Related
I can't explain it much in the title but I'm now stuck with having to test 2 variables for the same value and was wondering is there a way to do something like this.
var a = 'abc';
var b = 'def';
if (a=='abc' || b=='abc'){ c = 'z'; }
Now c is the variable that was tested true, so by assigning a value to c it would assign the value to the variable that tested true in the if statement. a and b can have different values but both can have the same value aswell.
No, the expression just yields a result value, with no information stored about which subexpression was truthy. (And separately, JavaScript doesn't have references to variables [at least, not that you can use in your code].) You'll have to break it out into two ifs:
if (a === "abc") {
a = "z";
} else if (b === "abc") {
b = "z";
}
It would be possible to do something like this if the variables were accessor properties (or other function calls) with side effects (since the right-hand operand of the || won't be evaluated at all if the left-hand operand evaluates to a truthy value). Or if they were properties in an object and you tested an array of property names, etc. But it would be unnecessarily complicated. :-)
You could take a switch statement, here you can check various variables agains a certain value.
switch ('abc') {
case a:
a = 'z';
break;
case b:
b = 'z';
break;
}
In my code, I have a function that creates a new map given a few parameters. I want to make it so that if no parameters are passed, some default values will be used.
Why won't this work:
function create(a,b,c) {
return new Map(a,b,c || 10,1,10); // create new map using a b c as parameters
// or 10, 1, 10 if none entered.
}
create();
Assume that there is a constructor function 'Map' that would accept and process these parameters.
What can i do besides having an if/else type check?
The shortest way i know under some limitations is to use
<var> = <var> || <defaultvalue>;
So
Return new Map((a = a || 10), (b = b || 1), (c = c || 10));
However this way its hardly readable and you might want to consider moving the assignments before the constructor.
The limitation however is that all falsy values lead to the default being assigned which might be a problem for some numeric values.
You can do it this way:
function create(a, b, c) {
a = typeof a !== 'undefined' ? a : 10;
b = typeof b !== 'undefined' ? b : 1;
c = typeof c !== 'undefined' ? c : 10;
return new Map(a, b, c);
}
Javascript does not offer default function value parametization.
I was looking through jQuery code $.extend()
I found this:
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
I was wondering what would happen if we move options = arguments[i] out of parenthesis?
a = b assigns b to a and returns b. Thus, (a = b) != c will assign b to a and then check b != c. The parentheses are because otherwise, != will be evaluated before = due to the operator precedence (comparison is evaluated before assignment - source)
a = b!= c
will work like,
a = (b != c)
since = operator has least precedence in all the operators.
e.g.
b = 5
c = 10
a = b != c
>>> false
>>> a will have false value here
Here is the precedence chart and demo
In case of (options = arguments[ i ]) != null, options will be assigned a value of argument[ i ] and then compared with null.
Assignment has less precedence than equality which means
arguments[i] != null
would be processed before
options = arguments[i]
Given a different result than what is desired.
To understand it a little better check here and read about operator precedence
I was wondering how this could be written in shorthand that the statement would execute
This one isn't working, but I see this kind of syntax lots of times in plugins - variables mixed with statements etc..
Can someone give an explanation regarding the proper use of this shorthand syntax?
I want to "execute" NOT "evaluate" the second statement if the first evaluates to true!
var succes = !data.user||(window.location = "users/profile");
I knew the first example was way to simple, This one is better, it also uses comma,s to string statements after eachother, I like to know how to learn this syntax.
},
hide: function (a,
b) {
if (f && !(500 > (new Date).getTime() - f.getTime())) {
if (!a || "number" == typeof a) a = k();
b || (b = $(".profile-popup"));
j(a) && (b.fadeOut("fast"), m(!1, a));
e && (clearInterval(e), e = null)
}
}
}
}();
EDIT
I changed my first example to use the && in my code and it worked, so, that's that - for anyone else reading -, and you should use absolute url's if working with window.location
I also found another detailed explanation over here.
thanks, Richard
I think you're missing another =:
var succes = !data.user || (window.location == "users/profile");
Your example assigns, whereas == is a comparison.
The general pattern of !obj || obj = "something" is simply shorthand for:
if (obj === undefined) {
obj = "something";
}
That's because !obj evaluates to false if it's undefined (the pattern also seems to assume that obj will not be defined as true).
Likewise, the pattern f(a) && (g(b), h(c)) is shorthand for:
if (f(a) == true) {
g(b);
h(c);
}
For the referenced piece of code:
var succes = !data.user||(window.location = "users/profile");
What this implicitly says is:
If data.user is undefined, then set success to true.
Otherwise (if data.user is assigned), then redirect to users/profile.
The exact meaning is anyone's guess without knowing the context, but it appears to mean "redirect the profile screen, if user data is available, otherwise ..."
Why would you use this syntax?
var myVar = myArray.length && myArray || myObject;
instead of
var myVar = myArray.length ? myArray : myObject;
Edit: I just had a thought that if in the case of the && || syntax both sides of the || evaluated to false, as you might expect if myObject was undefined or null, if false would be returned. But it isn't, the objects value undefined or null is returned.
true || true //true
true || false //true
false || true //true
false || false //false
Edit2:
!!(myArray.length ? myArray : myObject);
This does however return false if myObject is undefined or null
x && y || z is different than x ? y : z even if it "works" in the case presented.
Consider when y evaluates to a false-value (in the post y can't be a false-value when it is evaluated because it is dependent upon x and thus it "works" as expected).
Using ?: is the much better and more clear construct in this case. The only reason I can give for using the other syntax is "too much cleverness".
A ternary is the only correct thing to do here, unless you guarantee that myObject.name has a "true" value.
Consider
res = a ? b : c;
vs.
res = a && b || c;
What is the difference? The first does what it is supposed to. But the second tests a. If a is false, it gets c, as the ternary version.
But if a is true, it only gets b if this is true as well, if not, it gets c, what is not wanted at all.
Tastes vary. Maybe somebody just got in the habit of writing things like
var myName = myObject && myObject.name || "unknown";
and stuck with it even when a ternary would work as well.
http://jsperf.com/conditional-operators
It looks like you use && || when you want your code to go slower and you want to obfuscate it a little more :)
There's also a difference between what is going on.
foo && bar || foobar // if foo or bar is false, then foobar will be returned
foo?bar:foobar // the bar, or foobar, is decided solely on foo
If you wanted the ternary to act like the logical conditional it would be:
foo&&bar?bar:foobar