Unlocking Hidden JavaScript Features for Developers
Written on
Chapter 1: Introduction to JavaScript Features
JavaScript, like many contemporary programming languages, is built on two fundamental components: lexical grammar and a standard library. The grammar defines a unique syntax with reserved keywords and special characters that allow developers to write code. These grammatical rules facilitate the creation of self-documenting code tailored to various development tasks. In parallel, the standard library provides interfaces for utilizing pre-built, general-purpose functionality such as string handling, data structures, and date/time management.
JavaScript boasts a comprehensive, pre-loaded standard library featuring a range of objects for developers. For instance, the standard ArrayBuffer object enables manipulation of raw binary data. The grammar of JavaScript offers both basic syntax and modern features that empower developers to write code more efficiently and clearly.
In this article, I will unveil some of the obscure features of JavaScript's lexical grammar that are often overlooked by developers. By mastering these advanced capabilities, you can elevate your JavaScript skills and harness the full potential of the language!
Section 1.1: Tagged Template Literal Functions
Today, developers prefer using ES6 template literals for string interpolation over traditional concatenation methods. Template literals allow for the creation of strings by embedding expressions seamlessly within the string, resulting in a more readable syntax. Additionally, JavaScript supports tagged template functions that can parse template strings with customized logic.
Tagged template functions enable developers to manipulate segments of the parsed template string, allowing for tailored processing according to specific needs. For instance, consider the following cap tagged template function, which capitalizes every expression result:
function cap(strings, ...exps) {
return strings.reduce((acc, str, i) =>
(acc + str + (exps[i]?.toString()?.toUpperCase() ?? '')), '');
}
let str = cap`Hello ${'JavaScript'}... Hello ${'everyone'}...`;
console.log(str); // Hello JAVASCRIPT... Hello EVERYONE...
As illustrated above, you can manipulate evaluated template strings using parameters passed to the tagging function. Furthermore, you can even return objects from these functions. A practical application of this is using tag functions for converting string data to objects. Below is a json tag function that provides a cleaner syntax for parsing inline JSON strings:
function json(strings, ...exps) {
return JSON.parse(strings.reduce((acc, str, i) =>
(acc + str + (exps[i] ?? '')), ''));
}
let obj = json`{
"msg": "Hello JavaScript",
"code": ${1000}
}`;
console.log(obj); // {msg: 'Hello JavaScript', code: 1000}
Moreover, you can create tags for parsing YAML and HTML formats as well. The popular Google OpenSource zx library employs tagged template literals to enable Bash-like scripting in Node.js.
This video discusses "5 Must Know JavaScript Features That Almost Nobody Knows," showcasing various hidden features that can enhance your JavaScript programming skills.
Section 1.2: Native Non-Decimal Number Literals
While humans generally utilize the decimal system, programming languages often require the use of different numeral systems. In JavaScript, you can work with binary, octal, and hexadecimal number literals using specific prefixes:
let n1 = 0b101; // Binary
let n2 = 0o21; // Octal
let n3 = 0xff; // Hexadecimal
console.log(n1); // 5
console.log(n2); // 17
console.log(n3); // 255
As demonstrated, each non-decimal number is instantly converted to its decimal equivalent. The built-in toString() method and parseInt() function facilitate the handling of non-decimal numbers stored as strings:
let n1 = '0xff';
let n2 = parseInt(n1, 16);
console.log(n2); // 255 (decimal)
let n3 = n2.toString(2);
console.log(n3); // 11111111 (binary)
Although storing large binary data as strings is not optimal for performance, typed arrays provide a more efficient alternative.
Chapter 2: Preventing Object Modifications
JavaScript allows unrestricted manipulation of objects by default, including built-in objects:
JSON.parse = (str) => console.log(str);
For instance, you can disrupt a live website (for the current browser tab) by overriding a built-in method, as shown above. To prevent modifications to objects, you can use Object.seal() and Object.freeze() methods. For example, seal() stops new property additions while allowing existing property modifications:
const obj = {
a: 100,
f: () => console.log('Hello...')
};
Object.seal(obj);
obj.a = 1000; // works
obj.b = 100; // doesn't work
delete obj.a; // doesn't work
On the other hand, Object.freeze() restricts both the addition of new properties and alterations to existing ones:
Object.freeze(obj);
obj.a = 1000; // doesn't work
obj.b = 100; // doesn't work
delete obj.a; // doesn't work
By default, sealed and frozen objects do not throw errors for invalid operations, so enabling strict mode in JavaScript is necessary to catch these errors.
This video titled "9 JavaScript Features You've Never Used" dives deeper into lesser-known features that can enhance your coding experience.
Conclusion
In this article, we explored some of the lesser-known features of JavaScript that can greatly improve coding productivity by allowing for cleaner and more concise code. Alongside these features, enhancements such as the exponentiation operator and comma operator-like syntax improvements can help you code like an expert.
ECMAScript continues to evolve the JavaScript specification, with community proposals regularly discussed and maintained by the ECMAScript TC39 group on GitHub. Some proposals aim to enhance developer productivity by extending the JavaScript syntax, such as standardizing the function.sent meta-property and introducing function pipelines for all major web browsers.
Stay updated with the ECMAScript proposal repository to be among the first to learn about the latest features in JavaScript!
Thank you for reading!