I saw the following syntax in JavaScript that allows you to add functions to an Objects element so you can perform a switch alternative. Consider the following:
var insert = insert || {};
insert.Actor = function (user) {
//Do Somthing
}
This would allow you to do the following:
function addUser(type) {
if (insert[type]) {
return insert[type](user);
}
}
I like this implementation but I have two questions:
What exactly is this statement doing and could i just declare a regular object?
var insert = insert || {};
Besides readability what advantages do I get by using this instead of a regular switch statement.
You can add functions to any Object in JavaScript. The syntax you see just "says" If the object already exists... use it, otherwise, create a new object.
var insert = insert || {};
The variable insert is being set to itself, || (OR) being set to {} which is the short syntax for a new Object.
What exactly is this statement doing and could i just declare a regular object?
In JS, foo.bar results in a reference error if foo is not defined. var insert = insert || {}; ensures that insert will be an object, so that checks like if(insert[type]) will work as expected (insert[type] will be undefined)
More generally, || is the logical OR operator, which works as follows: http://www.ecma-international.org/ecma-262/5.1/#sec-11.11 if the left hand side expression (insert in this case) is a "truthy value" (including objects but not values like 0 or undefined), then the value is LHS; otherwise the value is the RHS expression.
Besides readability what advantages do I get by using this instead of a regular switch statement.
You would have to have many conditionals of the form if(insert) in every block of the switch statement. Using this method, you obviate most of them.
insert || {};
Return the first operant that is true from the left to the right.
This is a "OR" operator. In Javascript a "OR" operator dose not simply return true/false boolean value. This is just a short cut to say if insert is not defined, define it as an object.
It really depends on whether you have a reason to believe that insert has already been declared in that scope or not and whether it's the same insert you want or not. Obviously if insert has been defined somewhere else and doesn't do what you want it to do, then this syntax isn't helpful, because it's going to set insert in your scope to the insert that's already defined somewhere else.
Versus using a switch statement, it's a style preference. That's really all it amounts to. You have to ask yourself, "Who will be reading this, and what will be most helpful to them in understanding what this does?"
var insert=insert||{};
is equivalent to:
if (!insert) var insert={};
(if the insert object doesn't exist, create it)
The first expression just makes the code shorter.
This is often used in modular scripts, as any module could initialize the insert object which will then be reused by the other modules.
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 am trying to get a better grip on the JS syntax and I was wondering why it is common practice in many libraries to repeat the object name after a variable with that same name has already been declared. Please see below:
var Backbone = Backbone || {}; // <= Why the duplication?
or
var listeners = this._listeners || (this._listeners = {});
UPDATE:
After further research I have found a very well written article that evaluates many Idiomatic Expressions.
The article also explains the use behind Immediately Invoked Function Expressions (IIFE), i.e the wrapping of a function within a function, like such:
(function() {
console.log('Hello!');
})();
which is another one of those JS brainteasers that newbies like me can't quite understand.
var Backbone = Backbone || {};
means if Backbone is undefined or null or false, set it to {}
Longer explanation:
The assignment operator evaluates from right to left and logical operators(even though Javascript doesn't have real logical operators as they work on non-boolean operands as well) evaluate from left to right.
An expression like A || B returns B if A is undefined, null, or false.
So A = A || B either keeps A value if it already has one or assigns B to A.
var Backbone = Backbone || {};
As others have explained, this code will do the following:
declare a variable Backbone, check if a variable Backbone already
exists within the scope,
if yes, assign that object (in JS everything
is an object) to our declared variable (which, incidentally, has the
same name)
if no, it will create a new empty object.
The purpose of this is modularity. Lets' say you are loading a couple of Backbone plugins, along with the bare Backbone.
First, you loaded the base backbone.
The script checks if the root scope object checks if rootscope object Backbone exists (ie. window.Backbone)
It does not, so we create an empty one and do stuff with it.
Now, the next plugin script checks if root object Backbone exists (which it does)
Since it does exist, it doesn't create a new empty object, but uses the existing one
Now it goes like this until all your plugins are loaded.
This isn't entirely correct, but something like this happens.
This is a way to default the value of the variable only if it hasn't been assigned already. You could think of it as the JS way to do optional function parameters with default values.
JSHint give the following error:
Expected an assignment or function call and instead saw an expression.
For the following line of code:
(aFunctionOrNull) ? aFunctionOrNull() : someObject.someMethod();
It highlights the final ) on someMethod so I assume the error is there. The code works and JSHint doesn't have a problem when I change it to if () {} else {} syntax. I don't mind the longer syntax but I'd like to learn why JSHint says this and if this is a bad practice.
The biggest piece of confusion may come from the terminology. Is someObject.someMethod() not a function call?
Well, in general it's considered bad practice to call a function using the ternary operator(s), without assigning the return value (which is what you seem to be doing).Also, it could be worth checking what JSHint has to say about the following code:
(aFunctionOrNull || someObject.someMethod)();
If aFunctionOrNull is undefined (or null, or falsy), the logical-or-bit will cause the expression to evaluate to someObject.someMethod, and the resulting value of that is invoked (a reference to a function object, hopefully). This gives you the opportunity to write your code more "fail-safe" without the bulk of a nested ternary:
(aFunctionOrNull || someObject.someMethod || function(){})();
The grouped expression is now bound to evaluate to a truthy value, so no errors are thrown there.
To avoid JSHint nagging about your not doing anything with the return value, either assign it to a variable (which I don't really like doing), or add a little operator to the mix:
~(aFunctionOrNull || someObject.someMethod || function(){})();//bitwise not
!(aFunctionOrNull || someObject.someMethod || function(){})();//logical not, doesn't really matter which one
On your last question: someObject.someMethod is indeed a function call. More specifically, it's a call to a function object in the someObject's context.
For those who don't know this: JS functions are objects, and the called context is either explicitly set using the bind method (defined on the Function.prototype) or ad-hoc:
var referenceToMethod = someObject.someMethod;
referenceToMethod();//<-- inside the function objects, this now points to the global object
An easy way to think of it is that JS functions just float around aimlessly in memory/space/time, until they are called via a reference, the context of that reference is then passed to the function object, to determine what object it'll interact with. This is, sadly, the global object by default, or null in strict mode.
JSHint says about expressions, or expr:
This option suppresses warnings about the use of expressions where
normally you would expect to see assignments or function calls. Most
of the time, such code is a typo. However, it is not forbidden by the
spec and that's why this warning is optional.
While JSLint says:
An expression statement is expected to be an assignment or a
function/method call or delete. All other expression statements are
considered to be errors.
AFAIK, there's no problem in doing what you're doing only that it will issue a warning because it would expect you to use an if..else statement, but you can turn this off in JSHint with:
/*jshint expr:true */
There error is because a ternary is an expression. You could use it to set a variable:
var result = a ? b : c;
Notice that the ternary evaluates to either b or c. It's an expression.
That said, the warning (I believe) comes from the notion that ternaries suffer poorer readability than an if...else block. The code above can be rewritten
var result;
if (a) {
result = b;
} else {
result = c;
}
Which is easier to read than a ternary. JSHint does as much to promote readable code as it does valid code. If you're comfortable including these expressions in your code, go ahead and disable the warnings for expressions. (It's what I would do.)
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.
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