Generally, I test whether or not a variable is set with something like this:
if (variable !== '') {
do something...
}
I know there are other methods for testing variables like typeof but I don't see any advantage - is this an appropriate way to test whether or not a variable is set? Are there problems with it that I should be aware of ?
Two reasons:
1) What if the variable is set by getting the contents of an empty input box?
if(someScenario){
var variable = $('empty-box').val(); }
Perhaps this is only done in certain cases, like when someScenario is true. Later on, you want to check if that variable was set. Your means returns false rather than true. Point is, you can come up with scenarios where you get wrong answers.
There's just no reason not to do it the accepted way.
if(typeof variable !== 'undefined')
It's no slower, has no real flaws, and is only a few characters more.
2) And most importantly, using typeof makes it totally clear what you're asking. Readability is crucial, and if another programmer read the first code, they would think you were checking that it wasn't an empty string. The method using typeof makes it perfectly clear what your conditional is looking for, and reduces the odds of mistakes later on.
If variable has been declared but might not have a value then your code:
if (variable !== '') {
tests if it is not the empty string. Is that what you want? An empty string might be a valid value. Better to test for undefined, or explicitly initialise it to a value that you can then treat as "invalid" (perhaps null, or whatever suits).
If variable has not been declared at all the above code would result in an error such that execution would stop at that point - you can't test the value of a variable that doesn't exist. So if, for example, you're trying to test a global variable that is created inside a function that may not have been called yet, or perhaps you're using several JS files and one needs to test a variable that may or may not have been created by one of the other files, then the only way to do it is with:
if (typeof variable != "undefined") {
Since you're using strict equality testing, the following will all return true:
false
undefined
null
0
The only time your check will return false is when you pass in an empty string.
Is that what you want?
Check out coffeescript's existential operator, by searching "The Existential Operator" on this page: http://coffeescript.org/
The functional problem with your approach is that is that you may inadvertently assign a blank string to variable at some point prior in your script and your logic block will now do the wrong thing.
From a stylistic standpoint your solution is less desirable because your intent to check the existence of the variable is not clear. Someone who was just reading through your code for this the first time might misunderstand what you wrote to mean "I'm expecting there to be a variable named variable set to the blank string" as opposed to "Do something if this variable does not exist."
This might be highly subjective, but my recommendation is to avoid code, that needs to check, whether a variable is set (a.o.t. has some value or type).
Consider this snipplet
var a=false;
if (some_condition) a="Blah";
if (typeof(a)=='string') ....
if (a===false) ...
this makes sure, a is always set, while keeping it easily differentiable from '', null or 0
Related
Is there a shorthand way to replace a value with a different value in javascript?
Here's the most concise way I know of yet:
getAttr(data,"PARTITIONING_SCHEME") === "[None]" ? "" : getAttr(data,"PARTITIONING_SCHEME")
But that requires repeating myself, and in this case calling the getAttr function twice to get the same value. Obviously I can assign it to a variable once and then do the conditional logic, but that'd be another line of code and I'm looking for conciseness.
I suppose I could do a string replacement:
getAttr(data,"PARTITIONING_SCHEME").replace("[None]","")
But that would wrongly modify some longer string that happens to have [None] embedded in it. I'm sure regexp could do it but I'd prefer not to have frequent recourse to regexp... just need something quick, concise and easy to remember. Seems simple enough.
This is not asking about the javascript ternary operator ? which is what I showed above and requires repeating the operand on both sides, nor nullish coallescing ?? or || which only replace nullish values. I want to replace one non-nullish value with another, otherwise leave it alone.
I can do this of course by extending the String prototype:
String.prototype.swap = function(o,n) {
return this === o ? n : this
}
And then anywhere in my app:
getAttr(data,"PARTITIONING_SCHEME").swap("[None]","")
But wanted to check to see if there isn't something built-in first?
What about:
getAttr(data,"PARTITIONING_SCHEME").replace(/^\[None\]$/,"")
It will replace [None] only, when it is the only content of the string.
Or create a little utility function:
const noneBlank=s=>s=="[None]"?"":s;
// apply it here:
noneBlank(getAttr(data,"PARTITIONING_SCHEME"))
There is no reference type in javascript, therefore it is not possible to use
attr.someFunc()
or
someFunc(attr)
to assign attr to something else. A variable or attribute binding can only be changed via an assignment.
Surely you can use functions to change the content of the variable, but only when it is mutable. Therefore your imaginary String.swap is not possible either.
A realistic way to solve the problem at hand would be to have setAttr along with getAttr, to which you can pass a mutator function:
setAttr(data,"PARTITIONING_SCHEME", x => x === '[None]' ? '' : x)
I oftentimes see answers using strict comparison (===) instead of normal comparison (==) on status checking, i.e. here:
if(document.readyState === 'complete') ...
I would understand the reason if it were applied on empty string and the obtained value could be also other falsy value with different meaning. But when applied on non-empty string (like 'complete' in the sample), I believe the result is always the same for '==' and '==='. Is that so?
Some people measured that '===' can be faster, but I haven't seen a real world example where it would make any observable difference, so I don't take this micro-optimalization seriously.
On the other hand, anytime I see this operator, I read it as a warning "mind the type here!". But since document.readyState is always string, it annoys me that the original coder made me to study the code what other types there can appear - only to find out that only string.
To me, it is a strong reason to be polite to those who read my code and never use '===' when the type plays no role in the comparison.
Since '===' appears in similar cases in many SO answers and many expert pages, I would like to know if it is just social bandwagon or if there is any good reason why to use it in status checking.
I would recommend always using '===' instead of '==' when strict equality checking is required, which it is in most cases, for this reason: it declares intent. When I see code with '===', I will read it as 'a must be referentially or primitively equal to b'. When I see '==', I will read it as 'a must be coercibly equal to b'. From that, I will judge what kind of goal the code / original programmer is trying to accomplish and how they are passing data around to get the job done. Essentially, it yields insight into the context of the application, the way data is being passed around, and how this function / method / code block fits into the picture.
With that being said, if I see someone do 'a == b' when they are both strings, I'm not going to get on any high horse and make a fuss about it.
It always depends on what you want to achieve, and what you consider to be equal.
== is not always bad, but it often can lead to false assumptions.
If you have something like this:
class TestA {
toString() {
return 'complete'
}
}
class TestB {
valueOf() {
return 'complete'
}
}
let testA = new TestA()
let testB = new TestB()
console.log(testA == 'complete')
console.log(testB == 'complete')
Then testA == 'complete' might be exactly what you want, but because it does an implicit cast, you might do a false assumption about it being a string when it evaluates to true.
So if you later want to call something like substring on it, or passing it to another function that expects an actual string, then it might fail with an unexpected error.
Using === over == is mostly about maintainability, if you start to refactor code or if you look at older code and you see a == you always need to think about if you really want to have an implicit cast at that point or if it this was an accident. So you need to follow the code flow or check if it was documented.
Using an explicitly and === does not prevent you from doing other mistakes, but it keeps the code consistent.
I've been looking to at some old javascript on a website I run - hands up, I know very little about javascript.
I came across the following function:
var timeout = null;
function textareaResize() {
if (typeof(timeout))
clearTimeout(timeout);
timeout = setTimeout(function () {
refreshAutoGrowFields();
}, 200);
}
The intellisense tells me that the syntax typeof(timeout) is invalid, to be more specific 'unexpected constant condition', however this means nothing to me.
I'd appreciate it if someone could explain what should actually be there (if the intellisense is correct in its assumptions).
I'm not sure where that function was found, but it's definitely confusing, because it's actually inaccurate JavaScript.
What it's trying to do is make whats called a timeout, meaning a performance of a certain action or collection of code after a period of time.
In order to do this, it's attempting to set this "timeout" function to a pre-defined variable called "timeout".
The thing is, before they are setting it to the variable "timeout", for some reason they want to make sure that timeout hasn't already been set. Perhaps by setting it twice to setTimeout, it would potentially cause multiple functions to happen within the same amount of time (but perhaps not).
Anyways, in order to do that, they were trying to check if "timeout" has been set before.
The problem is the way they are checking it typeof(timeout), is completely incorrect, for 2 reasons.
First, the term "typeof" isn't usually to be used like a function call; rather, it is a keyword, much like var or return, so it shouldn't in general be used with ()s like it's used here, instead it should be used like typeof timeout == "null", but the problem is that even such a syntax would be completely invalid, because even if it was null, it wouldn't evaluate to "null", it would evaluate to "object", just try pasting the following JavaScript into a console:
typeof null
It should say "object", even typeof undefined is "undefined", which is a string, which, when put in an if statement, would still evaluate to true relatively speaking, so the if statement checking if timeout is defined or not was done completely wrong.
Instead, that if statement should simply be changed to if(timeout), removing typeof completely.
typeof will return the type of the variable you put inside.
These are some types in JavaScript
number
string
boolean
array
object
undefined
you can use the type as
let s1 = 'somevalue'
cosole.log(typeof(s1)) // prints 'string'
you can play around with that and change the contents of s1. Now to the comparing part, if you try something like
if(typeof(s1)=='number')
dothis()
else if (typeof(s1)=='string')
dothat()
tip : both are same
typeof s1
typeof(s1)
and typeof(typeof(someVar)) is always string, that's why the == operator works
Hope it helped and didn't confuse you further.
Until today, I had not known the with operator existed. I stumbled upon it while debugging an issue being thrown from a plugin (Backbone.Epoxy).
The operator creates block level scope for each property on the passed object.
var testObj = { "cat":true };
with (testObj) {
console.log(cat ? "Cat!": "dog"); // Cat!
}
Simple enough? Initially I thought this could potentially be really cool. Until I realized why my code was throwing an error. Here is an example derived from my code.
var testObj = { "css":true, "background-color":"blue" };
with (testObj) {
console.log(css ? background-color : ""); // throws
}
The actual code is a bit more dynamic, but this is essentially what occurs behind the scenes in the plugin. Since dashes are not allowed within variable names but are allowed in property names, which cause the error to be thrown.
So, to the questions:
Is there a way to sanitize the block scope local variable in order to avoid the issues with the dash while keeping it in my property name?
Has anyone else worked around this issue with epoxy?
You would have to make an exception and write:
testObj["background-color"]
As you may suspect, you cannot write just background-color, for the same reason you cannot write testObj.background-color. You should also ask whether using with, which is fairly non-standard, is worth the character-count savings. Usually the answer is "no".
I often find that I write IF statements which immediately reference the value of the conditional statement. For example, let's say I need to check to see if a string matches a pattern:
if (mystring.match(/mypattern/) {
var mymatch = mystring.match(/mypattern/)[1];
...
};
I suspect that what I'm looking for doesn't exist, but I've wondered whether you can reference the conditional statement's value within the if block, the way you can reference "arguments" within a function. In many cases, of course, I can rewrite it like this:
var mymatch = mystring.match(/mypattern/)[1];
if (mymatch) { ... };
But that's often not possible if there's a series of methods called. For example:
var mymatch = $('.myclass')[0].text().match(/mypattern/)[1];
... that would throw an exception if there were no item [0] on which to call .text(). Is there some convenient shorthand I'm missing out on? Or a better way to organize things? Just curious, really — I'll go on living if the answer is no.
In cases where relevant you can use the fact that the assignment operator returns a value in JavaScript, so for instance you can write things like:
if (assignedTest = testedValue) {
//value of assignedTest is now available
//and conditional will only be executed if true
This could be used if the RHS was compatible or properly set-up but it's also a huge readability concern since it's very easy to confuse the assignment = with comparison ==/===.
If you were particularly motivated to pursue this you could extract this type of functionality into a function that would behave in a reliable way: such as assigning the result of a closure to a named variable, and you could further tune the behavior to do other things (such as optionally evaluating to a different value within the test). Ultimately it would primarily be making a simple structure more complex though.