Looking through some JS code I have found something like this:
var a, b;
if (
(a = someFunction1(), b = someFunction2() )
){
...
}
I never found anything like this previously and I do not understand the reason for doing something like this. Therefore I am curious: is the person who has done this out of his mind or am I just not capable to understand his idea.
When I try to check what construct like (expression1, expression2) does, I see that it always returns the value of the second expression:
(5, 6) // 6
('strange', 'things') // 'things'
(4, undefined) // undefined
So if I would be the one writing this code, I would do something like this:
var a = someFunction1(),
b = someFunction2();
if (b){ ... }
Am I correct in my reasoning?
When I try to check what construct like (expression1, expression2) does, I see that it always returns the value of the second expression
Yes. Even without trying out, this is what the comma operator does.
Am I correct in my reasoning?
Yes. Your code does exactly the same thing, but is more readable.
You are correct, that is essentially if(b). The readability of the first version is terrible and does not save on space so it would make no sense for it to be minified like that.
Assigning variables inside of conditional statements is bad practice.
Related
I'm working on some existing code that looks something like this:
return this.getMyObject() && this.getMyObject().myArray[0];
As far as I can tell it is checking that the object returned by getMyObject() exists before returning the first item in it's myArray property. How does this work and is it good form?
Update: The reason for my question came from the confusion over how the && operator can be used to return a property value and not a boolean result. After further thought, to make it more readable I refactored the line to:
return this.getMyObject() ? this.getMyObject().myArray[0] : undefined;
Obviously I am assuming here that the myArray property will exist.
That code works because of type coercion. Some people will tell you its good and some people will say always truly check something using typeof
if (typeof someVariable === 'undefined')
Even in examples below the above check isn't enough. I don't know what is better but that code as far as I am concerned isn't how I write it myself but it is accepted with a lot of javascript developers. There are times that code in the correct conditions can still pass the first check and yet throw an error accessing the property. Depends how controlled your situation is that determines, to me, if you should or shouldn't allow it.
Example of passing first check and failing:
var myObject = 1;
var test = myObject && myObject.myArray[0];
Or as #JamesThorpe pointed out in comment above:
var myObject = {};
var test = myObject && myObject.myArray[0];
Also people familiar with some coding languages but not JS might look at that code and not understand what it means where checking with an if and then returning the value might be a bit more readable to others, which is also a plus I think.
It's correct form. If there is no object returned by this.getMyObject() then function will return false in another case second part of condition will be executed and returned as a result of function. It's good practice to check if object exists before calling any method on it, because an error could occur if not to do so.
But you should check an existence of an object only if you are not sure whether it exists.
this my very first question on stackoverflow, so please forgive me if I am not getting all the etiquette yet.
I am trying to work with a previous script written in JavaScript. There is an if conditional expression in the code that I do not understand. The reason it is confusing to me is because it has 3 arguments. I have never seen an if conditional expression like this in any language, or even in the JavaScript "if" tutorial on http://www.w3schools.com/js/js_if_else.asp. The code snippet I am working with looks like this
if (this.css(alldivs[i], "contentdiv", "check")){ //check for DIVs with class "contentdiv"
setting.contentdivs.push(alldivs[i])
alldivs[i].style.display="none"}
My question is: What does if(foo, bar, "check") mean? Is this an old deprecated string comparison function in JavaScript? Why are there 3 variables in the if conditional expression instead of 2?
What are the advantages of the previous code, compared to something like:
if (this.css(alldivs[i] === "contentdiv")
Thank you for your help.
What does if(foo, bar, "check")
When you have a conditional with comma separated expressions, only the last one matters (the previous ones are also executed, though).
Then, the code is equivalent to:
foo;
bar;
if("check") { /*...*/ }
But you have this:
if (this.css(alldivs[i], "contentdiv", "check"))
That means:
Run this.css(alldivs[i], "contentdiv", "check"), where this is an object which has a the method css (a method is a function which is a property of an object).
Check the returned value.
Maybe you will understand it better this way:
var temp = this.css(alldivs[i], "contentdiv", "check");
if(temp) { /* ... */ }
Let's break down what's happening here. In this line:
if (this.css(alldivs[i], "contentdiv", "check"))
You have two things going on.
You have a function call this.css(alldivs[i], "contentdiv", "check").
You have an if() that checks the return value from that previous function call
This would be equivalent to this expanded code:
var returnVal = this.css(alldivs[i], "contentdiv", "check");
if (returnVal) {
setting.contentdivs.push(alldivs[i]);
alldivs[i].style.display="none";
}
This:
if (this.css(alldivs[i], "contentdiv", "check")) {
Would be equivalent to this:
var temp = this.css(alldivs[i], "contentdiv", "check");
if (temp) {
So you see, it's not an if taking three parameters. It's an if with one parameter which happens to be a function call that takes three arguments.
It's hard to know what answer is going to help you, as your question is about code that doesn't appear in your sample. In this case:
if (this.css(alldivs[i], "contentdiv", "check"))
The condition is based on the return value of the call to this.css. In the sample you seem interested in:
if(foo, bar, "check")
The answer is that it's always going to evaluate as True because of the way the Comma Operator behaves in JavaScript.
I am reading a very comprehensive javascript programming book. In the "functions" section of language basics I have come to the following:
"The return statement can also be used without specifying a return value. When used in this way, the function stops executing immediately and returns undefined as its value. This is typically used in functions that don’t return a value to stop function execution early, as in the following example, where the alert won’t be displayed:"
function sayHi(name, message) {
return;
alert(“Hello “ + name + “, “ + message); //never called
}
I am trying to understand why anyone would want to do this. Why write a function that returns "undefined"? I have tried googling, and searching SO, but have not had much luck though this may be because I am not phrasing my search correctly as I am learning js.
Can anyone give me a real-world example of where this might be useful so that I can understand?
Usually it's a conditional return. Something like
function calculateSomething(obj, condition) {
if (condition !=0 ) return;
obj.data = obj.data * 42;
}
in this case if some condition fails - function exits right away. Otherwise data in a passed object is modified.
The function you provide is useless...
However, not every function needs to return something. Sometimes a function does things "elsewhere" and the value that is returned is irrelevant.
The function may have side effects, such as altering the state of the page. Then, the caller may not expect any return value.
In my opinion, learned from masters so to speak, the idea here is to only temporarily disable the function. So if you have like an x amount of function calls to sayHi() like for example in a repeater or spread out over multiple files, the idea can be useful to simply return; without a value. Useful? Yes, to avoid commenting out chunks of code, but that's it.
Leaving this in a development environment, which initially will enter the www, you should not write it like this, and always make sure that: when a function has to return "something", then "something" always counts for value, no matter what the condition. With lowest value a boolean => return false;. This counts for every code block inside that function => for if else while ...
/* INCORRECT: it only returns something conditionally */
function do(something){
if (condition){
return false;
}
}
/* CORRECT: it returns value no matter what the condition */
function do(something){
if (!condition){
return true;
}
return false;
}
/* OPTIMIZED: a lot of ideas can be optimized, especially when returning booleans */
function do(something){
return !condition;
}
The rules only apply if you want to write proper code. Using tools like jslint, jshint or re-sharper helps a lot in understanding the basic principles of writing ecmascript valid code. Since not everyone is aware of these rules, all examples will yield the same result. In the sens of "it works, but it's not valid code".
Because A JS function is an object(has:Attributs+methods)
And , An object should have a value which can be undefined .
The proof is that
function sayHi(){}
Can be handled such as object even calling it :
var returnedValue=sayHi.call() ;
If sayHi does not return anything, returnedValue will be undefined
Example if you want to use classes I am sure about it you will use setter functions to give value for an instance attribute.
Like this:
function Something(val) {
this.value = val;
}
In the following JavaScript statement:
var a = true;
a = a || b;
Will the a variable have an unneeded reasignment to it's own value?
Yes it will assign to a. This sort of thing probably wouldn't even be optimised in a compiled language.
It won't however waste time evaluating b however as it knows the result already. Something like this happens when a = a || b is run:
if a
a = a
else
a = b
EDIT:
To follow up what icktoofay said "it will not significantly impact performance.", it is simply setting a (boolean) variable which is one of the simplest operations that can occur. It will make little difference even if you're assigning to something more significant like a function or array as it will be assigning to a reference of the item, not creating it again.
Here is a performance comparison of doing nothing vs assigning to self (jsPerf link) thanks to #bfavaretto for setting it up.
a will be true when a or b is true. So yes, unless you insert some more code between those lines which can affect the value of a, the lower statement will always set a to true.
Yes - it won't be optimised away, because JavaScript doesn't optimise. Although the underlying parser implementation could conceivably optimise, I very much doubt it would in this case, and it would be very specific to the platform implementation.
While I was killing time looking up Javascript shorthand patterns, I came across an interesting way of expressing an if statement here. The following works:
var var1 = 5;
var var2 = 1;
var1 == 5 && var2++;
I think that's a totally cool (and shorter, cleaner) way of writing an if statement that only needs to do one operation. However, I ran into an issue with the following code as soon as I tried something else with it:
var var1 = 5;
var var2 = 1;
var1 == 5 && var2 = 2;
Instead of working like the first code snippet, my test throws an error:
Uncaught ReferenceError: Invalid left-hand side in assignment
Why doesn't this work, and why is the left-hand side of my statement being called out as incorrect as opposed to the right hand?
This doesn't work because the && operator has higher precedence than the = operator. In other words, your code is interpreted like this:
(var1 == 5 && var2) = 2;
If you manually put parentheses around the assignment, it will be interpreted correctly.
var1 == 5 && (var2 = 2);
Other people will reprimand you for writing code like this, saying that is a bad idea because it makes the intent of the code harder to read--which is true, especially for people unfamiliar with this idiom--but it is important to try it out and experiment with things like this to see for yourself what happens. You've already encountered one of the annoying things about this approach.
Anyway, in cases like this, I personally prefer to use single line if statements, like this
if(condition) statement;
Although I'm sure others will tell you that that's bad style because you have to manually add brackets when you need more statements, this hasn't really bit me and IMO it's cleaner than using three lines just for a simple condition, like you said.
Don't be alarmed that this doesn't work as you'd expect, in fact less than a month ago Brendan Eich (Creator of JavaScript) was sharing with us that this type of use is better known as an "abusage" of the language, since this logical operator isn't meant to execute code like this, but rather it's meant to determine the value of an expression.
"I also agree...that the && line is an abusage, allowed due to JS’s C heritage by way of Java, but frowned upon by most JS hackers; and that an if statement would be much better style..." http://brendaneich.com/2012/04/the-infernal-semicolon/
That being said, you can avoid the operator precedence issue by wrapping your statements:
(var1 == 5) && (var2 = 2)
because you are using an invalid operator on the right-hand side. its trying to read the entire statement as a single variable.
Is
var1 == 5 && var2++;
an cleaner or more understandable than this?
var2 += var1 === 5 ? 1 : 0;
In addition, the above expresses intent far more clearly than your code: the next guy who has to look at your code will see it and understand immediately what's going on, but looking at your code:
var1 == 5 && var2++
Is going to raise red flags in her head, because it looks like a bug or a some sort of typo — which means she's going to have to spend time trying to understand what you were actually trying to accomplish and whether or not the wonky code was intentional or not.
My first reaction, looking at
var1 == 5 && var2++ ;
Is that an assignment was intended:
var1 = 5 && var2++ ;
But the developer bounced the = key by accident, turning it into an orphaned expression (that happens to have side-effects).
Further, orphan expressions like that is likely to get flagged by any decent linter, for instance eslint's no-unused-expressions rule, as they indicate a probable bug.
Or
You could try using the ternary operator to make your code look concise.
When utilizing the '&&' operator fail or throw errors, I default back to the ternary operator.
Example:
let var1 = (conditional) ? "on true return" : "on false return";