Is there an equivalent of Swift's guard statement in JavaScript? - javascript

I'm starting to develop web apps but I come from the iOS world.
I was wondering if there was an equivalent of Swift's guard statement in JavaScript?
I love return early pattern.
For those who may not know, guard statement is a "return early if statement", here is a very basic example:
myCondition = trueOrFalse()
guard myCondition
else {print("myCondition is false")
return}
print("myCondition is true")

When inside a function you can return early. No need for an actual guard, you can use an if instead.
f () {
myCondition = trueOrFalse()
// Make sure `myCondition` is `true`
if (!myCondition) return console.log("myCondition is false");
console.log("myCondition is true")
}
PS: I return the log statement just to keep it on one line. console.log simply returns undefined, so your function will return undefined. You can split that statement on multiple lines if you think it looks better that way, or want your function return type to always the same as that might help with optimization (eg: always return an integer, so instead of undefined you could return 0).

Related

Using functions within conditionals

I've been doing Project Euler 'cause reasons. At one point, I found myself wanting to compare a value with the result of a function. I've since selected a different solution, but it's left me curious. How would this work? If I were to do something like:
//javascript
if x == mathyFunction(10){
//do this
}
function mathyFunction(y){
if(y>0){
mathyFunction(y-1);
return y;
} else {
return y;
}
}
I'm aware that this isn't tail recursive or anything fancy, I'm mostly just curious how the logic works behind this.
How would the computer interpret it? Would it return true if any one of the values == x or would it only return true if all the values == x. Experimentation has left me guessing, though I'll keep digging.
You didn't specify which language you're asking about, but assuming the usual semantics of the return statement, a function can't return more than once. So if by "return all values individually", you meant something like this:
function f() {
return 1;
return 2;
...
}
Then everything after the first return is just dead code and it's the same as if the return 1 was the only return statement in there. A function call has exactly one value and that value is what you're comparing against.
If you meant that mathyFunction returns a list or other collection object, which contains the values between x and y, then x will be compared to that list. Again the semantics will depend on the language, but in most languages comparing a number to a list will either be a type error or just false.
If by returning the values individually you were referring to a yield statement (like C#'s yield return or Python's yield), then the result of the function is going to be some kind of iterator object and the same thing as in the previous paragraph applies.

Confused about Javascript. A boolean function can act as a void function?

I'm trying to refresh some Javascript knowledge for an upcoming interview. I was reading a blog that says
"The delete operator returns true if the delete was successful."
and then shows an example of it in use:
var christmasList = {mike:"Book", jason:"sweater" }
​delete christmasList.mike; // deletes the mike property​
In that example it looks like delete is used in the manner that a void function (in the general programming sense -- I know that JS doesn't require declarations like void) would be.
Can someone explain to me, or give me a link to, the documentation that explains how JS functions can act with different return values, and does such require separate implementations for each return value?
You can check the Delete operator which says:
If desc.[[Configurable]] is true, then
Remove the own property with name P from O.
Return true.
Note that delete only works for properties of objects. Also a good read:- JavaScript Delete() Only Affects The Referenced Object Regardless Of Prototype Chain
In that example it looks like delete is used in the manner that a void function
The delete operator is not a function, it is an operator. It deals with properties of objects, not their values.
Functions are something else, but since you asked:
Can someone explain to me how JS functions can act with different return values
JavaScript is loosely typed. Functions don't care about the types of values unless they need to, and (most of the time) conversion between types is handled by operators.
If a function needs to are about what it is operating on, then it has to examine the value to see what it is.
For example:
function myFunction(myArgument) {
if (typeof myArgument === "function") {
return myArgument();
} else {
return myArgument;
}
}
A function can return any value it likes.
function string_or_number() {
if (Math.random() > 0.5) {
return 1;
} else {
return "1";
}
}
Strongly typed languages care about what type of value a function returns and what type of value is passed into an argument.
Loosely typed ones simply don't. There's nothing special about it from the point of view of someone using the language.
It shunts most of the complexity about having to care about types to the compiler author instead of the user of the compiler (who just has to care that, if a function is designed to do something to a duck, what they pass is sufficiently like a duck to not break the function).
As others note, delete is technically an operator and not a function; for our immediate concerns, however, the difference is academic, as the operator's behavior is the same as that of many functions used for their side effects (which is to say, void functions). Both the rule of the language and the conventions of their use are simple.
Rule
All functions provide a return value; if no return statement is reached, this will be undefined
Conventions
Since we always get a return value, we can take advantage of it to improve our programs. There are two conventions; which one should be used depends on the use case.
Return a boolean, signalling success or failure
Return some object being operated on
Option 2 is most useful for methods on objects: if our method changes the state of the object and then returns the object, we can bundle several changes into a single line of method calls: object.change1().change2().change3(newVal);
Option 1 is most useful when we want to use the success or failure of an operation to determine program flow; maybe we want to throw an exception if the property was not deleted but continue normally if it was. Then we can use if (delete object.property) to attempt to delete the property and branch into success/failure cases immediately.
From the MDN on the delete operator:
Throws in strict mode if the property is an own non-configurable property (returns false in non-strict). Returns true in all other cases.
I can't make it simpler than that. Aside from a small example:
alert(delete window.window)
alert(delete window.foobar)
alert(delete window.alert)
Javascript functions always return ambigious values. One function can return boolean, string, object, array or HTMLElement.
There is no fixed type.
function masterSwitch(input) {
switch(input) {
case 0 : return "Hello";
case 1 : return 0xdead;
case 2 : return 0.00042;
case 3 : return document.createElement("DIV");
case 4 : return true;
case 5 : return window;
case 6 : return this;
case 7 : return null;
default:window.alert("Please specify input from 0 to 8");
}
}
<input type="text" id="output"> <SELECT onchange="document.getElementById('output').value = typeof masterSwitch(this.selectedIndex);">
<option>string</option>
<option>int</option>
<option>float</option>
<option>HTMLElement</option>
<option>boolean</option>
<option>window</option>
<option>this</option>
<option>null</option>
</select>

Javascript best practice to use undefined as boolean evaluation?

In this simple javascript code, method verify returns a string if conditions do not match, else undefined. I am using undefined value in 'if' clause. Is this common / acceptable javascript programming practice?
if (verify(text)) {
alert(text + " is not bar");
}
function verify(foo) {
if (foo + "" != "bar") return "foo is not same as bar";
}
Yes, since you know the verification outcomes will be either truthy (a non-empty string) or falsy (undefined), it's perfectly fine to use it like that.
Here's a list of truthy and falsy values in JS, you might find them handy: http://www.sitepoint.com/javascript-truthy-falsy/
It is a common practise but in my experience its better to be explicit. For instance, I prefer:
verify(text) === undefined
The way I would suggest is to make the 'verify' to return a boolean value. The reason for this, is if for whatever reason you have a verification method that returns 0 (zero) and you do if (verify), the condition will be false but 0 is actually a verified value.
I hope that helps.
Although this is technically possible and works fine in most cases, I personally find it better style to design functions so that they always return the same type. My IDE warns me about inconsistent functions:
and this warning should be taken seriously. In particular, it helps you avoid unpleasant surprises when you test your app:
// hmm...
function isZero(n) {
if(n == 0)
return true;
}
// let's test it
describe("test", function() {
it("isZero", function() {
expect(isZero(0)).toBe(true);
expect(isZero(1)).toBe(false); // FAILURE!
});
});

What should a JavaScript constructor return if it fails?

If I have a javascript class which cannot be instantiated what should the constructor return that I can test for. The constructor always returns an object so I cannot return null if the constructor fails.
function SomeClass(id) {
if(typeof(id) === 'number' {
// This is good
this.id = id;
} else {
// This is bad
// This return is ignored and an empty object is returned
return null;
}
}
var a = new SomeClass('badParam');
if(a){
// is true even though the class expects a number.
}
// Could use this check
if(a.id !== undefined){
// Do some stuff
}
but it seems there should be a better way.
It is probably best to throw an exception to notify the caller that the initialization failed and to take appropriate action.
Return codes are fine, but for the most part there is no motivation for the caller to implement the checks on the return code.
My advice is to break hard and break soon. This will make contract violations very evident during testing.
Returning any non-object from the constructor is practically the same as exiting the constructor. (The constructor will return a new object, with a prototype if one was specified.)
So, returning null, undefined, or 42 from the constructor are equivalent.
Check out section 13.2.2 of the ECMAScript spec (pdf) for more info.
My first approach:
Don't allow a constructor to fail; consider alternatives
My second approach:
If a constructor fails, it must only fail because of a programming error and thus;
should throw an exception and;
must not return 'a status code' (see Emmett's answer for why returning null doesn't work anyway)
I have never designed a constructor (something invoked as the target of new) to return anything except an object of the "expected" type.
Fail fast, avoid being too clever, and save time debugging hard-to-find bugs.
Happy coding.
Use I sentinel. I like to
return {invalid:true};
This looks clean:
var x = new X();
if (x.invalid) { // ...
(There's no way to return a non-true value from a constructor, so you can't put new in the conditional as you might with another language.)

Why does a return in `finally` override `try`?

How does a return statement inside a try/catch block work?
function example() {
try {
return true;
}
finally {
return false;
}
}
I'm expecting the output of this function to be true, but instead it is false!
Finally always executes. That's what it's for, which means its return value gets used in your case.
You'll want to change your code so it's more like this:
function example() {
var returnState = false; // initialization value is really up to the design
try {
returnState = true;
}
catch {
returnState = false;
}
finally {
return returnState;
}
}
Generally speaking you never want to have more than one return statement in a function, things like this are why.
According to ECMA-262 (5ed, December 2009), in pp. 96:
The production TryStatement : try Block Finally is evaluated as follows:
Let B be the result of evaluating Block.
Let F be the result of evaluating Finally.
If F.type is normal, return B.
Return F.
And from pp. 36:
The Completion type is used to explain the behaviour of statements (break, continue, return and throw) that perform nonlocal transfers of control. Values of the Completion type are triples of the form (type, value, target), where type is one of normal, break, continue, return, or throw, value is any ECMAScript language value or empty, and target is any ECMAScript identifier or empty.
It's clear that return false would set completion type of finally as return, which cause try ... finally to do 4. Return F.
When you use finally, any code within that block fires before the method exits. Because you're using a return in the finally block, it calls return false and overrides the previous return true in the try block.
(Terminology might not be quite right.)
The finally block rewrites try block return (figuratively speaking).
Just wanted to point out, that if you return something from finally, then it will be returned from the function. But if in finally there is no 'return' word - it will be returned the value from try block;
function example() {
try {
return true;
}
finally {
console.log('finally')
}
}
console.log(example());
// -> finally
// -> true
So -finally- return rewrites the return of -try- return.
I'm gonna give a slightly different answer here: Yes, both the try and finally block get executed, and finally takes precedence over the actual "return" value for a function. However, these return values aren't always used in your code.
Here's why:
The example below will use res.send() from Express.js, which creates a HTTP response and dispatches it.
Your try and finally block will both execute this function like so:
try {
// Get DB records etc.
return res.send('try');
} catch(e) {
// log errors
} finally {
return res.send('finally');
}
This code will show the string try in your browser. ALSO, the example will show an error in your console. The res.send() function is called twice. This will happen with anything that is a function. The try-catch-finally block will obfuscate this fact to the untrained eye, because (personally) I only associate return values with function-scopes.
Imho your best bet is to never use return inside a finally block. It will overcomplicate your code and potentially mask errors.
In fact, there's a default code inspection rule set-up in PHPStorm that gives a "Warning" for this:
https://www.jetbrains.com/help/phpstorm/javascript-and-typescript-return-inside-finally-block.html
So what do you use finally for?
I would use finally only to clean-up stuff. Anything that is not critical for the return value of a function.
It may make sense if you think about it, because when you depend on a line of code under finally, you are assuming that there could be errors in try or catch. But those last 2 are the actual building blocks of error handling. Just use a return in try and catch instead.
why you are getting false is you returned in a finally block. finally block should execute always. so your return true changes to return false
function example() {
try {
return true;
}
catch {
return false;
}
}
Returning from a finally-block
If the finally-block returns a value, this value becomes the return
value of the entire try-catch-finally statement, regardless of any
return statements in the try and catch-blocks
Reference: developer.mozilla.org
As far as I know, the finally block always executes, irrespective of whether you have a return statement inside try or not. Ergo, you get the value returned by the return statement inside finally block.
I tested this with Firefox 3.6.10 and Chrome 6.0.472.63 both in Ubuntu. It is possible that this code may behave differently in other browsers.
Finally is supposed to ALWAYS run at the end of a try catch block so that (by specification) is why you are getting false returned. Keep in mind that it is entirely possible that different browsers have different implementations.

Categories