DEV Community

Cover image for 9 Extremely Powerful JavaScript Hacks
Klaus
Klaus

Posted on • Updated on

JavaScipt Hack 9 Extremely Powerful JavaScript Hacks

I like to optimize.

But users don't care about my optimized code if the site isn't working in their Internet Explorer 11 browser.

I use Endtest to create automated tests and execute them on the cross-browser cloud.

Netflix uses the same platform to test their web apps.

It's even listed as a Required Skill for some of their jobs.

Endtest does have some really nice features, such as:
• Cross-browser grid, running on Windows and macOS machines
• Codeless Editor for Automated Tests
• Support for Web Applications
• Support for both native and hybrid Android and iOS apps
• Unlimited Video Recordings for your test runs
• Screenshot Comparison
• Geolocation
• If Statements
• Loops
• Upload files in your tests
• An Endtest API, for easy integration with your CI/CD system
• Advanced Assertions
• Mobile Tests on real mobile devices
• Email testing with Endtest Mailbox

You should check out the docs.

Below are 9 extremely powerful JavaScript hacks.

1. Replace All

We know that the string.replace() function replaces only the first occurrence.
You can replace all the occurrences by adding /g at the end of the regex.

var example = "potato potato";
console.log(example.replace(/pot/, "tom")); 
// "tomato potato"
console.log(example.replace(/pot/g, "tom")); 
// "tomato tomato"
Enter fullscreen mode Exit fullscreen mode

2. Extract Unique Values

We can create a new array only with the unique values by using the Set object and the Spread operator.

var entries = [1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 4, 2, 1]
var unique_entries = [...new Set(entries)];
console.log(unique_entries);
// [1, 2, 3, 4, 5, 6, 7, 8]
Enter fullscreen mode Exit fullscreen mode

3. Convert number to string

We just have to use the concatenation operator with an empty set of quotation marks.

var converted_number = 5 + "";
console.log(converted_number);
// 5
console.log(typeof converted_number); 
// string
Enter fullscreen mode Exit fullscreen mode

4. Convert string to number

All we need is the + operator.

Be careful with this one since it only works with 'string numbers'.

the_string = "123";
console.log(+the_string);
// 123

the_string = "hello";
console.log(+the_string);
// NaN
Enter fullscreen mode Exit fullscreen mode

5. Shuffle elements from array

Every day I'm shufflin'

var my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(my_list.sort(function() {
    return Math.random() - 0.5
})); 
// [4, 8, 2, 9, 1, 3, 6, 5, 7]
Enter fullscreen mode Exit fullscreen mode

6. Flatten multidimensional array

Simply by using the Spread operator.

var entries = [1, [2, 5], [6, 7], 9];
var flat_entries = [].concat(...entries); 
// [1, 2, 5, 6, 7, 9]
Enter fullscreen mode Exit fullscreen mode

7. Short Circuit Conditionals

Let's take this example:

if (available) {
    addToCart();
}
Enter fullscreen mode Exit fullscreen mode

And shorten it by simply using the variable together with the function:

available && addToCart()
Enter fullscreen mode Exit fullscreen mode

8. Dynamic Property Names

I always thought that I first had to declare an object before being able to assign a dynamic property.

const dynamic = 'flavour';
var item = {
    name: 'Coke',
    [dynamic]: 'Cherry'
}
console.log(item); 
// { name: "Coke", flavour: "Cherry" }
Enter fullscreen mode Exit fullscreen mode

9. Use length to resize/empty an array

We basically overwrite the length of the array.

If we want to resize the array:

var entries = [1, 2, 3, 4, 5, 6, 7];  
console.log(entries.length); 
// 7  
entries.length = 4;  
console.log(entries.length); 
// 4  
console.log(entries); 
// [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

If we want to empty the array:

var entries = [1, 2, 3, 4, 5, 6, 7]; 
console.log(entries.length); 
// 7  
entries.length = 0;   
console.log(entries.length); 
// 0 
console.log(entries); 
// []
Enter fullscreen mode Exit fullscreen mode

I think it's really cool that you're looking for JavaScript hacks, but are you sure your Web Application is working correctly on all browsers and devices?

You can use Endtest to quickly create Automated Tests and execute them on the cross-browser cloud.

You don't even have to code in order to use it.

Seriously, just read the docs.

Cover photo by Laurie

Top comments (73)

Collapse
 
taufik_nurrohman profile image
Taufik Nurrohman • Edited

Return function shortcut:

// Before
function foo() {
    bar();
    baz();
    return 1;
}

// After
function foo() {
    return bar(), baz(), 1;
}
Enter fullscreen mode Exit fullscreen mode

Conditional shortcut variants:

// Before
return a ? a : b;

// After
return a || b;
Enter fullscreen mode Exit fullscreen mode
// Before
return a ? b : c;

// After
return a && b || c;
Enter fullscreen mode Exit fullscreen mode
// Before
return a && b ? c : d;

// After
return a && b && c || d;
Enter fullscreen mode Exit fullscreen mode
// Before
if (a && b) {
    c = d;
}

// After
a && b && (c = d);
Enter fullscreen mode Exit fullscreen mode
// Before
if (a) {
    b = c;
    d = e;
} else {
    b = e;
}
return f;

// After
return a && ((b = c), (d = e)) || (b = e), f;
Enter fullscreen mode Exit fullscreen mode
Collapse
 
razgandeanu profile image
Klaus

Interesting.
Thank you for sharing that.

Collapse
 
cristtopher profile image
Cristtopher Quintana Toledo

Nice!

Collapse
 
sami_hd profile image
Sami

Wow 😲

Collapse
 
stephenmirving profile image
Stephen Irving • Edited

I wanted to point out that #9 (using length to empty an array) is particularly useful if you are using ES6+ syntax and declaring your arrays with const instead of var. This keeps you from having to declare your array with let just to empty it.

I also wanted to share that according to tests I ran using several benchmarking tools, it is slightly faster on some browsers to convert a string to a number by multiplying it by 1 then by using the + operator as you do in #4:

const stringNum = "256.3"
const number = stringNum * 1;
console.log(number); // Logs 256.3

The difference is pretty negligible though. The fastest three methods were all very close in speed. Your method, the above method of multiplying by 1, and in a close third is using the Number constructor:

const number = Number(stringNum);

Here are another couple of quick things I've picked up.

A more performant and shorter replacement for Math.trunc(num) and parseInt(num), as well as working as a replacement for Math.floor(num) if you know the number won't be negative, using bitwise operator. This works on numbers stored as strings as well as regular numbers:

const num = 568.328;
const strNum = "243.782";

const truncatedNum1 = num|0;
const truncatedNum2 = strNum|0;

console.log(truncatedNum1); // Logs 568
console.log(truncatedNum2); // Logs 243

A more performant, albeit limited, way to fix a number to a single decimal place rather than use the incredibly slow num.toFixed(1):

const fixToOne = num =>
  (num = Math.round(num * 10) / 10) + (num === (num|0) ? '.0' : '');

fixToOne(2.3892); // Returns "2.4"

You can change the function by wrapping the returned value in parens and multiply by 1 at the end if you need a number returned rather than a string, but toFixed() returns a string so that's what I decided to return too.

A more performant but limited way to fix a number to two decimal places rather than use the incredibly slow num.toFixed(2):

const fixToTwo = num => 
  (num = (Math.round(num * 100) / 100) +
  (num === (num|0) ? '.0' : 0)) + (num === (num|0) ? '.0' : '') +
  (num * 10 === ((num * 10)|0) ? '0' : '');

fixToTwo(2.3892); // Returns "2.39"

You can see the benchmarks on these custom functions versus the native toFixed() and witness how drastic the speed difference is here: jsperf.com/decimal-rounding-tofixe...

Collapse
 
gustvandewal profile image
Gust van de Wal

"You can change the function by wrapping the returned value in parens and multiply by 1 at the end if you need a number returned rather than a string"

But the function already has a part that freshly generates the raw rounded number: Math.round(num * 10) / 10. Just leaving that part will do; no need to generate a number -> cast to string -> cast to number

Collapse
 
razgandeanu profile image
Klaus

That's really interesting.
Thank you for sharing that information with us.
I appreciate it.

Collapse
 
stephenmirving profile image
Stephen Irving

No problem. I added it to above post in an edit after your reply, but in case you didn't see it and are interested, you can check out my benchmarks for the custom toFixed functions here:

jsperf.com/decimal-rounding-tofixe...

It is DRASTICALLY faster as toFixed is painfully slow. Usually this wouldn't matter, but I had a usecase where I had an animation function that was getting called dozens of times a second and there were 3 places in it that required fixing a value to a set number of decimal places. Animation was noticeably smoother when I replaced toFixed with my custom functions.

Collapse
 
mburszley profile image
Maximilian Burszley

bitwise operator

Do note that limits the returns to 32-bit and will lose data on larger decimals/integers.

Collapse
 
andyghiuta profile image
Andy G

As a JS developer working in a team I would not do 7/9 things on this list to a colleague. Even more so I wouldn't do them to myself. Keeping things clear should be every developer's objective, otherwise we may as well write everything on one line and call it a day.

Collapse
 
mygeen profile image
Mygeen

I'm having my first ride as a frontend developer coming from the .Net world. I thought exactly the same but thought it might be due to lack of experience with JavaScript. Thanks for this comment, it confirms my suspicions!

Collapse
 
itepifanio profile image
Ítalo Epifânio

And if you use .Flat(Infinity) you flat all

Collapse
 
jack_garrus profile image
Nadia Guarracino

That resize/empty an array is a kinda bad practice, imho, because you mutate the original array

Collapse
 
vuesomedev profile image
Gábor Soós

Useful examples 👍

The word hacks makes me feel you write about dirty shortcuts, but these are actually absolutely good solutions to every-day problems. I wouldn't call them hacks.

Collapse
 
mburszley profile image
Maximilian Burszley • Edited

Eh.. I wouldn't use most of them in production code (like shortcutting over using an if statement).

Collapse
 
danoswalt profile image
Dan Oswalt • Edited

Probably not in a class or function, but it's super useful in template code or jsx when you are in need of a terse expression, such as to say 'if object exists, render object.property'... user && user.name, etc

Thread Thread
 
mburszley profile image
Maximilian Burszley

Leave terse to compilers unless it makes your expression more clear.

Collapse
 
vuesomedev profile image
Gábor Soós

Yes, that one makes code less readable

Collapse
 
razgandeanu profile image
Klaus

Thank you.
You do have a fair point.
But any word I thought of (tricks, shortcuts, etc) felt like a synonym for "cutting corners".

Collapse
 
learnbyexample profile image
Sundeep

The replace all trick with regexp will work only if string to search doesn't contain regexp metacharacters like ., ^, etc. You'll have to escape them first. developer.mozilla.org/en-US/docs/W... provides an escape function.

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

'abc a;c a.c apc a.c'.replace(/a.c/g, 'X')
// gives "X X X X X"

'abc a;c a.c apc a.c'.replace(new RegExp(escapeRegExp('a.c'), 'g'), 'X')
// gives "abc a;c X apc X"

String.prototype.replaceAll is proposed to avoid such issues: github.com/tc39/proposal-string-re...

Collapse
 
razgandeanu profile image
Klaus

Interesting.
Thank you for sharing that with us.

Collapse
 
weeb profile image
Patrik Kiss • Edited

available && addToCart()

Mindblow

Collapse
 
benbot profile image
Benjamin Botwin

You can chain it together many times AND you can do nicer looking deep undefined checks

‘niceobj && niceobj.maybeUndefined && niceObj.maybeUndefined.functionOrValue’

Way cleaner than if statements, but not as clean as typescripts “?.” operator

Sorry for the poor formatting. On mobile.

Collapse
 
benbot profile image
Benjamin Botwin

Oh I just found out the “?.” operator might be coming to JS too and it’s already in Babel.

I highly encourage you to take a look!

dev.to/akirautio/optional-chaining...

Thread Thread
 
razgandeanu profile image
Klaus

Interesting.
Thank you for letting us know.

Thread Thread
 
mburszley profile image
Maximilian Burszley • Edited

It's not "might"; it's in stage 4 and will be added in ES2020.

Thread Thread
 
benbot profile image
Benjamin Botwin

Even better!

Collapse
 
metalmikester profile image
Michel Renaud

It's a good thing I read this article because if I had ever came across this I would have wondered what it was.

Collapse
 
razgandeanu profile image
Klaus

Felt the same way when I found out about it.

Collapse
 
stephenmirving profile image
Stephen Irving

I also wanted to point out that #7 is especially useful when you are using ternary expressions, as you cannot chain an if statement within a big ternary, but you can using the && operator. A simple example would be using a ternary to write an if/else-if (rather than a basic if/else):

(condition
  ? truthyFunction()
  : condition2 && falsyFunction()
);

The corollary to this tip is using the || operator to basically say "If this is false, do the following":

condition || falsyFunction();
Collapse
 
jstewart8053 profile image
jstewart8053 • Edited

I noticed the same thing... adding

entries.flat(Infinity)
Enter fullscreen mode Exit fullscreen mode

will flatten the array down to a single array no matter how nested the array is :)
Oh... and also, super-helpful Post!

Collapse
 
hnnx profile image
Nejc • Edited

How exactly does this work?

var my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log( my_list.sort(function() {
return Math.random() - 0.5 //why 0.5?
}));

also, aren't arrays fixed size like in Java?

Collapse
 
kh136 profile image
k

Math.random() returns a number between 0 and 1. -0.5 is so that the result is between -0.5 and 0.5. The end result is half the time the comparator will be negative and half the time it will be positive, basically a coin toss function. And no they're not, they're more like python lists.

Collapse
 
softmantk profile image
NIKHIL CM

Hi, Can you explain Why it is not like a coin toss function ? I thought it is...

Collapse
 
ygorbunkov profile image
ygorbunkov

The output of #5 (array shuffler) is not that random. I use my own implementation of Fisher-Yates:

const shuffle = arr => arr.reduceRight((r,_,__,s) => (r.push(s.splice(0|Math.random()*s.length,1)[0]), r),[])
Collapse
 
sumnanazadi profile image
Sumnan Azadi

Thak you man, you just saved me a lot of time.

Collapse
 
ifarmgolems profile image
Patrik Jajcay

Flatten multidimensional array

Your example only works for 1 depth max, no?

Collapse
 
razgandeanu profile image
Klaus

That is correct. Good observation.

Collapse
 
iteniasim profile image
iteniasim • Edited

I am new to programming so can someone tell me what ... Means? Its being used in number 2 and number 9. Everyone seems to know about as no one is talking about it.

And that set method could have come in handy a few days ago, gonna have to find the code and change my looping logic to get the unique data from array with set method

Collapse
 
joeberetta profile image
Joe Beretta

... meanse spread/rest operator. U would google it like "JS spread operator"

Collapse
 
iteniasim profile image
iteniasim

Thank you for replying, i kept searching for ... And nothing showed up. But the explanation was very clear and simple once i knew what to search.

Thread Thread
 
joeberetta profile image
Joe Beretta

I found, that these links are useful for you: post on scotch.io and definition of spread on MDN

Collapse
 
metruzanca profile image
Samuele Zanca
y.length = x

This is really interesting. Good to know.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.