Multiple checks into one in JavaScript - javascript

I know that this may sound stupid but I was wondering if this code could be written in a shorter version:
if (this.myVeryLongName.aRandomProperty === 'property_1' || this.myVeryLongName.aRandomProperty === 'property_1' || this.myVeryLongName.aRandomProperty === 'property_1') {
//do something
}
maybe something like this:
if (this.myVeryLongName.aRandomProperty === ('property_1' || 'property_1' || 'property_1')) {
//do something
}
Is any way to make it short and still have same functionality?

You can make an array and use includes, like:
if ( ['property_1','property_2','property_3'].includes( this.myVeryLongName.aRandomProperty ) ) {
//do something
}
Doc: includes

Potentially even better option (than the one I posted in a comment)
switch(this.myVeryLongName.aRandomProperty) {
case 'property_1':
case 'property_2':
case 'property_3':
doSomethingHere();
break;
// if you have more cases, add them here!
}
Notice how this is much more easily readable, and extendable in future if needs change.

There's a variety of ways to do this:
['property_1','property_2','property_3'].includes( this.myVeryLongName.aRandomProperty )
(ES 2016)
['property_1','property_2','property_3'].indexOf( this.myVeryLongName.aRandomProperty ) !== -1
(ES 5)
/^(?:property_1|property_2|property_3)$/.test( this.myVeryLongName.aRandomProperty )
(Any JS version)

Related

Does Javascript have a way to do "in" when I want to see if a value is one of many?

My code looks like this:
if (testStatusId == 4 || testStatusId == 5) {
This is just a simplified version for the question.
Does Javascript have anything like an "in" where I would not need to repeat testStatusId for every number check?
You could make an array like:
if([4,5].includes(testStatusId)) { ... }
You'll need a polyfill for it as it's not universally supported. (ex: https://www.npmjs.com/package/array-includes-polyfill)
You could use indexOf with the same approach with wider compatibility:
if([4,5].indexOf(testStatusId) !== -1) { ... }
var j = [4,5];
if(j.indexOf(testStatusId) !== -1){
//your code here
}
switch (testStatusId)
{
case 4:
case 5:
// do whatever
break;
case 6:
// something else
break;
default:
// everything else
}
You could do this:
if([4,5].indexOf(testStatusId) !== -1) {
}
Although the code you have is probably already the best, if they is only two numbers.

jQuery - how to write a if promt checking for childNode.length, nextSibling and childNode.nodeType

I need some good examples of how to write a if-statement checking all my div's for specified number of childNodes.lenght and childNode.nodeType.
And in addition to be 100 percent sure i got the right <div> and its right node also check for the nextSibling.
I am pretty new to jQuery/javascript so i might struggle in the syntax but here is what i got so far:
var specifiedChildNodesLength = ...
var specifiedChildNodesType = ...
if( $('div').childNodes.length == specifiedChildNodesLength &&
$('div').childNodes.nodeType == specifiedChildNodesType) { do something }
Try this:
if (($('div').children().length == specifiedChildNodesLength) && ($('div').children().get(0).nodeType == specifiedChildNodesType)) {}

Javascript Error (IE): Object doesn't support this property or method

2015 Note: Everyone should go look through their old questions and be encouraged by how far they've come. There are so many things wrong with this code – it's wonderful.
This code works PERFECTLY in Firefox, and in IE the line ending 'negative'); breaks. I have no idea how to fix it! Argghhh!
$(".topline strong").digits().each(function () {
s = $(this),
c = "change";
if ($(s).hasClass(c) & $(s).text().replace(/%/gi, "") > 0) {
$(s).addClass("positive");
}
if ($(s).hasClass(c) & $(s).text().trim().charAt(0) == "-") $(s).addClass("negative");
});
Please use && instead of & (unless it's meant for minimizing)
String.trim isn't widely implemented yet. Use
$(s).hasClass(c) && /^\s*-/.test($(s).text())
instead.
I'd rather rewrite the code as:
$(".topline strong").digits().each(function() {
var s = $(this);
if (s.hasClass("change")) { // no need to $() an already $()-ed object.
var value = parseFloat(s.text());
if (value != 0)
s.addClass(value > 0 ? "positive" : "negative");
}
});
Instead of .trim() you can use $.trim() like this:
$(".topline strong").digits().each(function () {
var s = $(this), c = "change";
if (s.hasClass(c) && s.text().replace(/%/gi, "") > 0) { s.addClass("positive"); }
if (s.hasClass(c) && $.trim(s.text()).charAt(0) == "-") s.addClass("negative");
});
Also note the s changes, there's no need to clone it as another jQuery object each time, it already is one so use it :) As for the error: .trim() isn't in all browsers, this is why jQuery includes the $.trim() function (same reason it has $.inArray(), IE doesn't have .indexOf()).
Also when declaring variable use var, otherwise you're creating global variables.
As an aside for future readers of this, jQuery 1.4.3+ will use the native String.prototype.trim if it's available when calling $.trim().

shorter conditionals in js

I have conditionals like this:
if (foo == 'fgfg' || foo == 'asdf' || foo == 'adsfasdf') {
// do stuff
}
Surely there's a faster way to write this?
Thanks.
You might consider a switch-case statement
switch(foo) {
case "fgfg":
case "asdf":
case "adsfasdf":
// ...
}
It's not really any shorter, but could be more readable depending on how many conditions you use.
I would keep the conditionals the way they are. Any clever way of shortening them would make the code less idiomatic and less readable.
Now, if you do care about readability, you could define a function to do the comparison:
if( foo_satisfies_condition(foo) ) {
// ...
}
Or:
if( is_month_name(foo) {
// ...
}
If you give the function a name that faithfully describes what it does, it will be easier to understand the intent of the code.
How you implement that function would depend on how many comparisons you need. If you have a really large number of strings you're comparing against, you could use a hash. The implementation details are irrelevant when reading the calling code, though.
if (/^(fgfg|asdf|adsfasdf)$/.test(foo)) {
or:
if (["fgfg", "asdf", "adsfasdf"].indexOf(foo) != -1) {
Cross-browser support for Array.indexOf is still limited. Also, these are faster to write, probably not faster to run.
No need for using indexOf or a regex if you just use a hash table:
var things = { 'fgfg' : 1, 'asdf' : 1, 'asdfasdf' : 1 };
if ( things[foo] ) {
...
}
Here's a easy way:
String.prototype.testList = function(lst) {
lst = lst.split('|');
for(var i=0; i<lst.length; i++){
if (this == lst[i]) return true;
}
return false;
};
To use this function, you can just do this:
if (foo.testList('fgfg|asdf|adsfasdf')) {
You can also rename testList to whatever you want, and change the delimiter from | to anything you want.
Depending on the situation you could do..
//At some point in your code
var vals = new Array('fgfg', 'asdf', 'adsfasdf');
//...
if(vals.indexOf(foo) >= 0)
Ternary operator looks good if you like and has else
Use tilde (~) for a shorter expression
if (~["fgfg", "asdf", "adsfasdf"].indexOf(foo)) {
//do stuff
}

Finding in a predefined set of text options

Say, I want to see if a DOM element is a block. I can write it in three ways, depending on my mood:
// first way
if (el.currentStyle.display == "block" || el.currentStyle.display == "inline-block" || el.currentStyle.display == "table-cell")
// second way
var blocks = {"block": 1, "inline-block": 1, "table-cell": 1};
if (el.currentStyle.display in blocks)//
// third way
if (el.currentStyle.display.match(/block|inline-block|table-cell/))
I have mixed feeling about all of them. First is too verbose once I have more than one option. Second contains those arbitrary values in the object (where I put 1s this time). Third looks like overkill. (What exactly is bad about overkilling?)
Do you know another, better way? If no, any cons I am missing about these three ways?
Javascript only, please.
I like the third way; I don't think it looks like overkill at all. If you need an even shorter way then this works too:
el.currentStyle.display.match(/(e-)?(block|cell)/)
But that's not very readable...
It might be worth abstracting it all away by extending the String prototype:
String.prototype.matches = function(what) {
return (',' + what + ',').indexOf(',' + this + ',') > -1;
};
// Using it:
el.currentStyle.display.matches('block,inline-block,table-cell');
If we're primarily aiming for readability, and if this is happening more than once -- perhaps even if it is just once -- I'd move the test to a function. Then define that function whichever way you like -- probably option 1, for max simplicity there.
Overkill? Possibly. But a gift to the programmer who wants to scan and understand the code 6 months from now. Probably you :-)
function isBlock(el) {
return (el.currentStyle.display == "block" ||
el.currentStyle.display == "inline-block" ||
el.currentStyle.display == "table-cell");
}
// ...
if (isBlock(el)) {
// do something
}
Can't you use the 2nd way but check if it's undefined and then skip the ": 1" part. I haven't tested though.
It looks like you need an inArray function, here is one from the top search result:
Array.prototype.inArray = function (value) {
var i;
for (i=0; i < this.length; i++) {
if (this[i] === value) {
return true;
}
}
return false;
};
Then the forth way would look like this:
if (['block','inline-block','table-cell'].inArray(el.currentStyle.display))
Or in a more readable manner:
var isBlock = ['block','inline-block','table-cell'].inArray(el.currentStyle.display);
My prefered solution for this is:
'block||inline-block||table-cell'.indexOf( el.currentStyle.display ) >= 0
I think that this will use native code of the string and be way more efficient than the array & iteration method.

Categories

Resources