Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I moved one years ago from classic OO languages such like Java to JavaScript. The following code is definitely not recommended (or even not correct) in Java:
if(dayNumber = getClickedDayNumber(dayInfo))
{
alert("day number found : " + dayNumber);
}
function getClickedDayNumber(dayInfo)
{
dayNumber = dayInfo.indexOf("fc-day");
if(dayNumber != -1) //substring found
{
//normally any calendar month consists of "40" days, so this will definitely pick up its day number.
return parseInt(dayInfo.substring(dayNumber+6, dayNumber+8));
}
return false;
}
Basically I just found out that I can assign a variable to a value in an if condition statement, and immediately check the assigned value as if it is boolean.
For a safer bet, I usually separate that into two lines of code, assign first then check the variable, but now that I found this, I am just wondering whether is it good practice or not in the eyes of experienced JavaScript developers?
I wouldn't recommend it. The problem is, it looks like a common error where you try to compare values, but use a single = instead of == or ===. For example, when you see this:
if (value = someFunction()) {
...
}
you don't know if that's what they meant to do, or if they intended to write this:
if (value == someFunction()) {
...
}
If you really want to do the assignment in place, I would recommend doing an explicit comparison as well:
if ((value = someFunction()) === <whatever truthy value you are expecting>) {
...
}
I see no proof that it is not good practice. Yes, it may look like a mistake but that is easily remedied by judicious commenting. Take for instance:
if (x = processorIntensiveFunction()) { // declaration inside if intended
alert(x);
}
Why should that function be allowed to run a 2nd time with:
alert(processorIntensiveFunction());
Because the first version LOOKS bad? I cannot agree with that logic.
I did it many times. To bypass the JavaScript warning, I add two parens:
if ((result = get_something())) { }
You should avoid it, if you really want to use it, write a comment above it saying what you are doing.
There is one case when you do it, with while-loops.
When reading files, you usualy do like this:
void readFile(String pathToFile) {
// Create a FileInputStream object
FileInputStream fileIn = null;
try {
// Create the FileInputStream
fileIn = new FileInputStream(pathToFile);
// Create a variable to store the current line's text in
String currentLine;
// While the file has lines left, read the next line,
// store it in the variable and do whatever is in the loop
while((currentLine = in.readLine()) != null) {
// Print out the current line in the console
// (you can do whatever you want with the line. this is just an example)
System.out.println(currentLine);
}
} catch(IOException e) {
// Handle exception
} finally {
try {
// Close the FileInputStream
fileIn.close();
} catch(IOException e) {
// Handle exception
}
}
}
Look at the while-loop at line 9. There, a new line is read and stored in a variable, and then the content of the loop is ran. I know this isn't an if-statement, but I guess a while loop can be included in your question as well.
The reason to this is that when using a FileInputStream, every time you call FileInputStream.readLine(), it reads the next line in the file, so if you would have called it from the loop with just fileIn.readLine() != null without assigning the variable, instead of calling (currentLine = fileIn.readLine()) != null, and then called it from inside of the loop too, you would only get every second line.
Hope you understand, and good luck!
If you were to refer to Martin Fowlers book Refactoring improving the design of existing code ! Then there are several cases where it would be good practice eg. long complex conditionals to use a function or method call to assert your case:
"Motivation
One of the most common areas of complexity in a program lies in complex conditional logic.
As you write code to test conditions and to do various things depending on various
conditions, you quickly end up with a pretty long method. Length of a method is in itself a factor that makes it harder to read, but conditions increase the difficulty. The problem
usually lies in the fact that the code, both in the condition checks and in the actions,
tells you what happens but can easily obscure why it happens.
As with any large block of code, you can make your intention clearer by decomposing it and
replacing chunks of code with a method call named after the intention of that block of code. > With conditions you can receive further benefit by doing this for the conditional part and
each of the alternatives. This way you highlight the condition and make it clearly what you > are branching on. You also highlight the reason for the branching."
And yes his answer is also valid for Java implementations. It does not assign the conditional function to a variable though in the examples.
I came here from golang, where it's common to see something like
if (err := doSomething(); err != nil) {
return nil, err
}
In which err is scoped to that if block only. As such, here's what I'm doing in es6, which seems pretty ugly, but doesn't make my rather strict eslint rules whinge, and achieves the same.
{
const err = doSomething()
if (err != null) {
return (null, err)
}
}
The extra braces define a new, uh, "lexical scope"? Which means I can use const, and err isn't available to the outer block.
You can do this in Java too. And no, it's not a good practice. :)
(And use the === in Javascript for typed equality. Read Crockford's The Good Parts book on JS.)
You can do assignments within if statements in Java as well. A good example would be reading something in and writing it out:
http://www.exampledepot.com/egs/java.io/CopyFile.html?l=new
The code:
// Copies src file to dst file.
// If the dst file does not exist, it is created
void copy(File src, File dst) throws IOException
{
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
It's not good practice. You soon will get confused about it. It looks similiar to a common error: misuse "=" and "==" operators.
You should break it into 2 lines of codes. It not only helps to make the code clearer, but also easy to refactor in the future. Imagine that you change the IF condition? You may accidently remove the line and your variable no longer get the value assigned to it.
you could do something like so:
if (value = /* sic */ some_function()){
use_value(value)
}
Related
I'm currently doing some JavaScript programming and don't like having to type else if everytime I need to use it. I would much rather just type elif. I have done tons of research and don't know how I could get something like this... look at code ... to work where I can still say elif, but it is recognized as else if and I would be able to use it without the program.
elif = else if;
let x = 20;
if (x >= 21) {
console.log('psych bwah!');
} elif (x <= 19 ) {
console.log('umm... nope try again bud!');
} else {
console.log('ladies and gentlemen we gotem!');
}
I really want this to work so badly. And it would be so mind pleasing to understand how to rewrite pre-made code in terms that I want to use. Another example of what I'm trying to accomplish would be re-assigning the console.log() printing function to something shorter but still does the exact same thing, maybe c.l() as a shorter version, just for example though.
Having the ability to assign already usable normal JavaScript code to my own version of code is the task I guess I am trying to accomplish, if that makes sense. This way I can shorthand it and make everything way faster than I'd be able to before. So what I am really looking for is a better/working way, because my current method seen above in the code doesn't work, is maybe some form of a method or other way of changing the name of an if...else keeping the same function just typed/said different in code.
Answer:
Yes, it's possible.
As a note, it's not a great idea to do this for any production projects for a multitude of different reasons, however, it's a rather simple process for toy code or snippets.
How:
You can create a text/template script tag, parse it for Regular Expressions or Plain Text - just like any other String - replace it with whatever you would like, then place it in a Function constructor and call it.
A longer explanation I wrote in an article a while back can be found here: https://medium.com/wdstack/understanding-javascript-micro-templating-f37a37b3b40e
A larger example with a couple of different code adjustments ( for instance instead of if(a === b || a === c) you can write if(a === b || c) ) can be found here: https://codepen.io/zfrisch/pen/ENpvOq
Basic example of Elif:
var scriptText = document.querySelector('#microTemplate').innerText,
parsed = scriptText.replace(/elif/g, "else if"),
fn = new Function(parsed);
fn();
<script id="microTemplate" type="text/template">
let a = 5;
if(a < 5) console.log("a is less than 5");
elif(a === 5) console.log("a is 5");
else console.log("a is greater than 5");
</script>
NOTE Keep in mind these examples aren't filled with full-proof Regular Expressions. This is just a bare-bones example of how you can do simple transpiling. For instance if you put a string in the above code with "elifant" it will write "else ifant".
Conclusion
I don't know if I've stressed this enough, haha, but seriously do NOT use this in Production. :)
In any case I hope this trick helped answer your question! Happy Coding!
You can't assign a statement to a variable, you can only assign an expression.
if,else, and else if are all statements (along with try/catch, switch, for, while, etc..)
So in short, there is no real way that bit can work.
To alias an existing function you simply assign the existing function to a new variable, like so:
const c = {}
c.l = console.log
c.l('console','.','log','arguments')
I come from a compiled-language background (C/C++/Objective-C) and am currently writing a full-fledged application in JavaScript. (TypeScript actually, but my question is the same for both.)
The problem I'm running into is that if a single error occurs, the entire flow of execution halts. For instance, if I have:
myFunction()
{
doSomethingA();
doSomethingB();
doSomethingC();
}
then if doSomethingA() has something like this:
var myValue = window.myData.myValue;
but "myData" doesn't exist on "window" at the time, then all code STOPS EXECUTING... doSomethingB() and doSomethingC() do not execute, and a console error is logged. That might be fine for simple web pages, but I'm creating an application, and it needs to not 'stop working' inexplicably.
Granted, I can use try/catch to be 'aware' of this error, but that STILL doesn't solve my problem: I would like to write the code in a way such that doSomethingB() and doSomethingC() continue to execute, even if a problem arises.
However, this is a huge over-simplification of my code. Imagine there are MANY of these functions. It would be impractical to surround each with its own separate try/catch block. Even if I did, I need the rest of a given function to continue to execute even if something in the first part fails.
Of course, I can 'protect' my variables by using:
if ( typeof window.myData != "undefined")
or
if (window.myData.hasOwnProperty("myValue")
but that becomes very messy if you have several levels to check, such as when accessing:
var myValue = window.myData.something.anotherLevel.somethingElse.value;
Now I have to check if myData, something, anotherLevel, and somethingElse are all valid before accessing this value 'safely'. This results in very ugly code.
Is there a better way to make my code more 'bullet-proof'? If a property is unexpectedly missing, I need code to continue executing after the problem statement. Is that possible without 'protecting' every single statement that accesses data that has even a tiny chance of being undefined?
That's just how JavaScript is. It's not a strongly-typed language. You have the right approach checking for falsy/undefined. You could look into a utility library, something like Lodash's isUndefined() method to help ease the pain a bit. They have a lot of helper methods like that such as checking for object types, arrays, object literals, etc.
https://lodash.com/docs#isUndefined
Normally You have to have some set of "nested if hells" like:
if(typeof window.myData !== 'undefined' && typeof window.myData.something !== 'undefined' && typeof window.myData.something.anotherlevel !== 'undefined' ...) {
}
To ease developers pain there is utilities for example lodash
it's very helpful and shortens Your code.
it has _.get(object, path) function that takes element by path and if not found it just returns undefined.
<script src="https://raw.githubusercontent.com/lodash/lodash/4.13.1/dist/lodash.js"></script>
<script>
window.myData = {
something: {
anotherlevel: {
value: 'YOU GOT ME! (:'
},
zerolevel: {
value: 0
}
}
};
function getDataByPath(path) {
var result = _.get(window, path);
alert(result);
}
</script>
<button onclick="getDataByPath('myData.something.anotherlevel.value')">
anotherlevel.value
</button>
<br/><br/>
<button onclick="getDataByPath('myData.something.zerolevel.value')">
zerolevel.value
</button>
<br/><br/>
<button onclick="getDataByPath('myData.something.unexistentlevel.value')">
unexistentlevel.value
</button>
Your best bet would be to check, if the variables you use are undefined or not with
typeof window.yourVariable === "undefined"
It's however not very safe to rely on variables in the window object, use scopes and closures.
I'm accepting Prefix's answer, since I don't like accepting my own answers. And, it's useful to hear about the Lodash helper, and know that the "nested if hells" I have are a normal (sad to hear it!) part of JavaScript.
However, the 'solution' I've gone with that has ended up making me feel very happy, is to actually reject a premise in my original question: that try/catch is not a good solution.
Turns out try/catch, combined with attempting to make sure variables are undefined, is a good way to catch those cases that I've missed.
I've actually ended up architecting it as follows. Let's say I have lots of functions I want to happen as a result of doStuff(), and I've put them into window.callbacks. I can then do (untested pseudocode, but it gives you the gist of it):
doStuff() {
for (var myFunc in window.callbacks) {
if (window.callbacks.hasOwnProperty(myFunc) ) {
try {
window.callbacks[myFunc].call();
}
catch(err) {
console.log("%cCaught error in " + myFunc + ": " + (err.stack || err), 'background: #222; color: #bada55');
}
}
}
}
This logs a unique console log message, complete with stack trace, showing what triggered the error, and yet CODE EXECUTION CONTINUES. Subsequent callbacks will still be called. The only code that doesn't execute is the remainder of the callback that caused the error.
Given my compiled-language background, this gives me warm fuzzy feelings... it means that at worst, a tiny function will fail to execute, not an entire code path following an error.
So, I am geocoding addresses from the Google Places API. There are 38 Google address component types, and we have ~5 in-house address component types, so I need a system of mapping a number of Google types to our in-house types, with fallbacks.
For example:
var neighbourhood = googleResponse.neighborhood || googleResponse.sublocality_level_2 || googleResponse.sublocality_level_1
What is the best/cleanest/most efficient way to do this? Basically, I need to assign a var to some returned value, unless that returned value is undefined, and then move down the chain.
I think your approach is sound - using the short-circuiting ORs feels a lot cleaner than having some sort of branching statement to me. My two recommendations would be:
You should probably add some kind of hard-coded value (an empty string, perhaps? Depends on your use case) as a final fallback, so that if all of the options aren't found, you don't end up with the variable being set to something unexpected. I think being 100% explicit about all the possible things that could be returned is always a good practice.
I'd recommend pulling that logic out into a function, so that if you want to reuse it elsewhere it'll be more maintainable. Even if you don't think you'll need to use it again, it's still worth doing in case you change your mind later on - having to go through and replace every instance of a piece of code is incredibly tedious! It also makes your code a lot easier to test - you can pass in a hard-coded googleResponse and check that the output matches your expectations.
So my approach would probably look something like this:
function getNeighborhood(googleResponse) {
return googleResponse.neighborhood
|| googleResponse.sublocality_level_2
|| googleResponse.sublocality_level_1
|| "";
}
var neighborhood = getNeighborhood(googleResponse);
EDIT:
In response to your comment, there's a couple of options I can think of for values that have to be concatenated.
If it's just a matter of "everything or nothing", you could write this quite elegantly with a ternary expression:
function getStreet(googleResponse) {
return googleResponse.street_number && googleResponse.route
? googleResponse.street_number + googleResponse.route
: "";
}
However, if you start trying to nest these with fallbacks, it's going to get very unreadable very fast. At that point, you're better off just relying on a if/else if/else - it's a bit long winded, but it's comprehensible, and that's more important in my eyes.
function getStreet(googleResponse) {
if (googleResponse.street_number && googleResponse.route) {
return googleResponse.street_number + googleResponse.route;
}
else if (/* fallback */) {
return /* concat here */;
}
else {
// Make sure to always return a value, even if all of
// the other fallbacks fail!
return "";
}
}
I'm learning Javascript and I wrote the following code:
if (mystring.len > 0) {
// do stuff
}
I accidentally used .len instead of .length. To my surprise, no error was raised. mystring.len returned undefined and this made the comparison fail but the code kept right on running. I would prefer an actual error to be raised so I can fix the code. Adding "use strict" didn't help, nor did jslint.
I know there are ways to actively check whether or not a property exists, but that's not what I'm looking for. I want Javascript to tell me when I've made a typo in a property name.
Is there a way to cause Javascript to give an error in this case?
Nope - that is how JavaScript works and it's incredibly useful. Who is to say that checking len is something that needs fixing? Consider:
if(mystring.len === undefined) {
mystring.len = "Test";
}
The best you can do is to simply check that the thing is defined before using it:
if(mystring.len !== undefined) {
}
I appreciate the strangeness, and how it doesn't feel robust (having originally come from a C# background) but there isn't a lot you can do unfortunately. The fact that JavaScript is case sensitive makes this even more frustrating. You will learn to live with it though!
If you really really wanted to run some static analysis then you could considering creating a transpiler (e.g. Babel) extension to run this sort of analysis - but it would get really difficult if you ever expected something to be undefined which I find is common place.
edit
Here's a real example that I'd use where undefined is useful. I'm working with a library that needs to move stuff from one location to another. It can't do that unless the original location has been specified, so I might write something like the following, initializing values if I don't have them for some reason:
function update(node) {
if(node.x === undefined) { node.x = 0; }
node.y = node.y || 0; // This is the shorthand way I'd actually write it
// Do some other stuff
};
"use strict" (in my experience) is used so that variables that aren't explicitly declared/instantiated that are then referenced will throw errors (else, JS would just make a new var on the fly). So that wouldn't help here.
This sounds like an error that would typically be picked up by a compiler in other languages, but since JS is interpreted, you won't have that kind of explicit error checking unless you're in a beefy IDE. Are you using a text editor or something to write JS?
Thats not the way JavaScript considers your above code. Every variable in JS is an object. So, when you do mystring.len, its actually trying to access the len property of mystring obj and when it doesn't find that property, it will return undefined - which is how it should be. Thats why you will not be able to find any error using JSLint.
Just to give you an example -
var myObj = {name: 'Hello', id: 1};
console.log(myObj.name); // Returns 'Hello'
console.log(myObj.text); // 'undefined'
In order to prevent such code from giving you any errors, you can easily use the hasOwnProperty() method like follows-
if(myObj.hasOwnProperty('text')) doSomething();
Since myObj doesn't have any property text, the doSomething() function will never be called.
This is the behaviour of JavaScript as mentioned by many/all answers. However there is an option to prevent new properties you might want to try:
Object.seal https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
The simple answer is JavaScript is not ment to be typesafe...You shouldn't check it, but if you still want to check you can do it by:
if ('len' in mystring){
}
You should look into Typescript if you ask this question...
Yeah, read properly. In the last time I saw different patterns of argument validation in JavaScript (functions) and wondered which of them would be best-practice. At first I'll show two example code snippets. The first shows an (in my words) "immediate" argument/condition validation and the second one a "delayed" validation. Each of them affect the appearance of following code in different ways. Up to now I always used the "immediate" validation. But slowly I am getting doubtful if it's reasonable to force the whole following code into such conditional blocks. Please tell me what you think and what might be the "best" pattern.
And what about the place where variables are declared? A few times I read, that ALL variables should be declared on to of the method, before they're actually used. Is this correct? Because I think that it is useless to declare variables before it is sure that they'll be actually used (maybe invalid arguments force the throw of an Exception), I moved the variable-declaration-part beyond the argument/condition validation part. Is this advisable?
Thanks!
First example:
if ( colorStops.constructor === Array
&& colorStops.length
&& colorStops.every(function(c) {
return c instanceof ColorStop
}))
{
var privateVar1 = "foo",
privateVar2 = "bar",
privateVar3 = "tutifrutti";
// here goes the code
}
else {
throw new TypeError("GradientCanvasFacade: cannot add Colors; " +
"invalid arguments received");
}
Second example:
if (cg instanceof ColorGradient) {
throw new TypeError("PresetManager: Cannot add preset; " +
"invalid arguments received");
}
var privateVar1 = "foo",
privateVar2 = "bar",
privateVar3 = "tutifrutti";
// here goes the code
// Here goes the code that get executed when no explicit
// return took place ==> all preconditions fulfilled
Since JavaScript variables are scoped to the declaring function and not to the block as most other languages, declaring variables at the beginning of the function makes alot of sense.
function someFunc()
{
if (1==1)
{
var x = 1;
}
else
{
var x = 2;
}
return x
}
Now imagine a function a lot more complex, to me atleast, declaring x at the beginning makes alot of sense. For variables generally bound to a block (like iterator variables or collections) I still declare them in the block though.
I would definitely go for your second example not because it fails earlier, because really it doesn't, but because it's easier to remove and add validations this way without breaking a complicated if structure.
I'd go with the second, simply because it's easier to read. Also, with the first, if your function is very long, someone looking at the bottom, will wonder what that } is for, and have to hop up to the top to see.
Also the scoping of variables is very clear, even for someone who forgets that javascript has weird scoping rules.
Also, as mentioned by Martijn, the second method makes it a lot easier to check for various errors, ie each can have their own if statement and so on.
if (some condition) {
if (some other condition based in the first) {
if (another condition based in 1st and 2nd) {
do_job();
} else?
} else?
} else?
Where to put the else block? After every if or after the last?
It seems absolutely more readable the second choise