Some features that every JavaScript developer should know in 2025 (part 3)
Published on

After publishing the article "Some features that every JavaScript developer should know in 2025 (continued)", I have compiled a new list of other cool features (old and new) that I am going to share with you.
Function "named" arguments
Have you ever seen a function with tons of arguments, where some of them might have default values? For example, something like this:
function connectToDb(
dbUrl, username, password, encoding = 'utf-8',
portNumber = 3000, timeout = 30
) {
// do something...
}
Now, you want to pass a custom value for argument timeout
, for example, 20
. For you
this means
an unpleasant situation where you have to pass all the arguments that come before timeout
, even the
ones that have a default
value:
connectToDb('jdbc:mysql://some_host', 'some_username', 'some_pass', 'utf-8', 3000, 20);
We probably don't want to pass the default values 'utf-8'
and 3000
again by code
duplication, since the default values are already set. So, how to solve this problem when we
want to override only some arguments?
This problem can be solved by using the object destructuring and default value syntax:
function connectToDb(
dbUrl, username, password,
{ encoding = 'utf-8', portNumber = 3000, timeout = 30 } = {}
) {
console.log(dbUrl, username, password, encoding,
portNumber, timeout);
// do something...
}
connectToDb('jdbc:mysql://some_host', 'some_username', 'some_pass', { timeout: 20 });
// 'jdbc:mysql://some_host', 'some_username', 'some_pass', 'utf-8', 3000, 20
connectToDb('jdbc:mysql://some_host', 'some_username', 'some_pass');
// 'jdbc:mysql://some_host', 'some_username', 'some_pass', 'utf-8', 3000, 30
Although some other languages like PHP or Dart support named function arguments natively and have a more elegant syntax, this works very well and it's the closest thing to named arguments that you can imagine.
Dynamic code execution via Function objects
I think many of us have heard about
eval()
and some even used for code execution. Actually eval()
is a terrible way to execute
code, and you
probably shouldn't use it. The reason is because eval()
can also access the local
variables, which means it's less safe and also runs
slower:
function f() {
let a = 1;
eval("++a");
console.log(a); // 2
}
f();
The correct way of code execution is by constructing
Function
object and calling it. Function
constructor accepts one or more arguments. If one argument is
passed, it's interpreted as a function body, if multiple arguments are passed, the last one is interpreted as
a function body, the rest are interpreted as argument definitions. Here are some examples:
{
// A simple function without arguments
const f1 = new Function('console.log("f1")');
// A function with arguments and return statement
const f2 = new Function('a', 'b', 'return a * b;');
// A function with default arguments and return statement
const f3 = new Function('a = 1', '{b = 2, c = 3} = {}', 'd = 4', 'return [a, b, c, d];');
let a = 1;
// A function that attempts to access a local variable
const f4 = new Function('++a');
f1(); // "f1"
console.log(f2(6, 8)); // 48
console.log(f3()); // [1, 2, 3, 4]
console.log(f3(10, { c: 30 })); // [10, 2, 30, 4]
f4(); // error since "a" is not a global variable
}
Warning, any code execution has potential risks, and you should never execute any untrusted code.
Reading and writing cookies via cookieStore
Many people who have dealt with cookies with JavaScript know how painful and complicated are cookie
manipulations
(parsing, saving) via
document.cookie
.
This is why
cookieStore
was added as part of the Cookie Store API. With
cookieStore
cookie manipulations become a breeze. Here are simple examples of using
cookieStore.get()
,
cookieStore.set()
,
cookieStore.delete()
and
cookieStore.getAll()
:
// A basic way of setting as key and value
await cookieStore.set('cookie1', 'Cookie one');
// An advanced way of setting via object
await cookieStore.set({
name: 'cookie2',
value: 'Cookie two',
expires: new Date('2026-05-27T20:00:00.000Z'),
});
console.log(await cookieStore.get('cookie1'));
// { name: 'cookie1', value: 'Cookie one', expires: null, ... }
console.log(await cookieStore.get('cookie2'));
// { name: 'cookie2', value: 'Cookie one', expires: 1779912000000, ... }
console.log(await cookieStore.getAll());
// [{ name: ..., value: ..., ...}, {...}, ... ]
await cookieStore.delete('cookie1');
console.log(await cookieStore.get('cookie1')); // null
This feature is not supported in Firefox yet, so don't use it in production code without polyfills.
Exponentiation operator
Some people might not know but JavaScript has operator **
which raises a number to some power:
console.log(3 ** 4); // 3 * 3 * 3 * 3 = 81, the same as Math.pow(3, 4)
console.log(0.25 ** -0.5) // 2
console.log(3n ** 4n); // 81n
Reverse array methods
JavaScript arrays methods typically iterate from left to right, such as
find()
or
findIndex()
.
However, modern JavaScript also supports methods that iterate from right to left:
console.log([1, 2, 3].findIndex((x) => x % 2 === 1)); // 0
console.log([1, 2, 3].findLastIndex((x) => x % 2 === 1)); // 2
console.log([1, 2, 3].find((x) => x % 2 === 1)); // 1
console.log([1, 2, 3].findLast((x) => x % 2 === 1)); // 3
console.log([1, 2, 1].indexOf(1)); // 0
console.log([1, 2, 1].lastIndexOf(1)); // 2
console.log([1, 2, 3].reduce((acc, cur) => acc + cur, '')); // "123"
console.log([1, 2, 3].reduceRight((acc, cur) => acc + cur, '')); // "321"
Fast number truncation
In JavaScript numbers can be truncated to integers without using
Math.trunc()
by using bitwise operations. This can improve performance because we make the code more inlined by avoiding the overheads of the function calls.
Note that this will not work correctly for numbers that have more than 32 bits (less than / equal to
-2147483649 or greater than / equal to 2147483648), so use it with caution.
This works because when you apply bitwise operations to numbers, they are converted to 32-bit integers. Here are examples:
console.log(10.3 | 0); // 10
console.log(10.3 ^ 0); // 10
console.log(10.3 << 0); // 10
console.log(~~10.3); // 10
console.log(Math.trunc(10.3)); // 10
console.log(-10.3 | 0); // -10, works for negative numbers as well
console.log(Math.trunc(-10.3)); // -10
console.log(2147483647.1 | 0); // 2147483647
console.log(Math.trunc(2147483647.1)); // 2147483647
console.log(-2147483648.1 | 0); // -2147483648
console.log(Math.trunc(-2147483648.1)); // -2147483648
console.log(2147483648.1 | 0); // -2147483648, doesn't work correctly
console.log(Math.trunc(2147483648.1)); // 2147483648
console.log(-2147483649.1 | 0); // 2147483647, doesn't work correctly
console.log(Math.trunc(-2147483649.1)); // -2147483649