I'm working on a script that accepts a settings object, but uses default values where settings are not provided.
I just wrote the following line of CoffeeScript:
iframe_width = settings?.iframe?.width? ? $iframe_body.width()
My intent, in plain English, is:
If the settings object is defined, and it defines a property iframe, and the iframe property defines a property width, then assign the value of the latter property to the variable iframe_width. Otherwise, assign the value returned by calling $iframe_body.width().
Does my CoffeeScript code reflect my intent, and is it the most effective way to express that? It seems awkward with all of the existential operators (?), so I wanted to put it out there for some feedback (the compiled JavaScript is very terse and cryptic, so it's hard to tell if should work as intended).
Also, I'm not sure whether there's any redundancy in using both the standard existential operator (?) and its accessor variant (?.) together.
Thanks!
Update:
The code above doesn't seem to work as expected; however, this does:
iframe_width = settings?.iframe?.width ? $iframe_body.width()
That makes sense, since I don't think the former code actually accesses the width property, but rather just checks for its existence (twice, even?). In this code, I removed the ? just after the width property, since I think that's redundant with the ? operator between the two expressions. Does that seem correct?
(Note: This answer was written before the question was updated. As the questioner realized, foo? ? bar isn't just redundant—it actually won't work, because foo? evaluates to true or false, and is therefore always non-null.)
You have two good options for simplifying this: One, you could replace the existential binary operator with an or:
iframe_width = settings?.iframe?.width? or $iframe_body.width()
Two, you could ditch the ? after width—it's redundant:
iframe_width = settings?.iframe?.width ? $iframe_body.width()
Now, you could do both if and only if iframe.width will never be 0 (since 0 or x is x). If you can be sure of that, go ahead and make it
iframe_width = settings?.iframe?.width or $iframe_body.width()
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 sometimes have to write code in JavaScript that handles both null and undefined the same way. For example, a function that removes from an array every item that is either null or undefined. How should I name the function?
removeNullAndUndefined is very long. removeNull is short but imprecise. Ideally I want to name it removeX, where X has the meaning "null or undefined".
Does anyone know a good word for X?
Yes: Nullish. For instance, in the current Stage 3 Nullish Coalescing Operator proposal.
So: removeNullish or similar.
When I need to check for null or undefined I often name such function either isNil or isNothing e.g.
const isNil = thing => thing === null || thing === undefined;
If you must adopt a naming convention I'd opt for what's quite common to see in functional programming, namely the Maybe monad which comes with a subtype to represent nothing: Nothing or None.
If you look at monetjs:
The Maybe type is the most common way of representing nothingness (or the null type) with making the possibilities of NullPointer issues disappear.
Maybe is effectively abstract and has two concrete subtypes: Some (also Just) and None (also Nothing).
Under the hood, it uses a isNothing function for checking for null or undefined
In ramda.js, such function is called isNil:
Checks if the input value is null or undefined
(Lodash has a similar method with the exact same name.)
I'm trying to find the name of the practice (in any language) in which one checks for an object to be in existence before performing a lookup on it. Usually this is done by throwing in an && in between the object and the object lookup expression, like so in JS:
var example = objectName && objectName.thing;
such that example is evaluated to either undefined or objectName.thing, and avoids a runtime error.
I could have sworn I've heard this before, but I've completely forgotten. What is this practice called?
This is sometimes called a "guard," since the truthiness of the left operand guards access to the right operand. Of course, it's just a logical AND, but the use of AND in this specific context is occasionally called a "guard".
From Douglas Crockford's A Survey of the JavaScript Programming Language:
The && operator is commonly called logical and. It can also be called guard.
From Guard and Default Operators of JavaScript by Sean McArthur:
In Javascript, the way the languages determines logical operations and the values Javascript treats as true or false lead to people using the AND and OR operators for guard and default situations
This practice is sometimes called validation, or evaluation. You can use a ternary operator to do so.
var example = objectName ? objectName.thing : null
This will assign objectName.thing or null to example depending on objectExample
CoffeeScript has such syntax sugar:
item.getFoo?().fooParam?.bar
Which translates into long javascript equivalent with getFoo==null and fooParam==null checks. The question is: are there any ways to use this syntax in vanilla javascript with a library/translator/compiler other than CoffeeScript? We use Traceur in our project, but it doesn't have such syntax because it is not ES6 compliant (although I wish it to). Maybe some way to implement it within Traceur fork?
If you don't want the exact CoffeeScript semantics, you can cheat a bit:
return item.getFoo ? (item.getFoo().fooParam || {}).bar : undefined;
There are a few tricks going on here.
The ternary operator is used to test the truthiness of item.getFoo
If fooParam is missing, falsey, or absent, we substitute it with an empty object. CoffeeScript would have bailed out here.
We return the value of bar regardless of whether it exists. If it does exist, you get the value you want. If it doesn't exist but fooParam is set, you get undefined. If it doesn't exist because fooParam was undefined and we fell back to {}, you still get undefined.
You can write some helpers if the ternary operator gets in the way:
function defaultObject(input) { // A helper to put somewhere
return input || {};
}
return defaultObject((item.getFoo || defaultObject)().fooParam).bar;
This is even trickier: defaultObject will return {} when called with getFoo, so you don't need a ternary operator around the function call. If fooParam isn't truthy, defaultObject will return another empty object, eliminating the need for another ||. If fooParam is truthy, defaultObject behaves like the identity function and returns it.
I'm sure this could be golfed further down, but I'd recommend avoiding this pattern. Anyone reading your code will be fairly confused and blame you for making a mess in the codebase.
I had this same question recently, and I came here hoping for a better solution than my current one. If you're doing this frequently, it's easier to make a function to do it for you:
var qm = function(arg) {
if (arg instanceof Object) return arg;
return function(){};
};
Then to use it, you wrap your objects in it to make sure no error is raised. It starts to look ugly if there are many question marks on a line
qm(qm(item.getFoo)().fooParam).bar
The optional chaining operator ?. was introduced in ES2020.
obj.val?.prop
obj.val?.[expr]
obj.arr?.[index]
obj.func?.(args)
It is supported by the browsers of 91.81% of internet users as of 29 November 2021 according to https://caniuse.com/mdn-javascript_operators_optional_chaining.
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