Eyes, JAPAN Blog > Keeping up to date your JavaScript arsenal

Keeping up to date your JavaScript arsenal

Mola BogdanGeorgii

Intro.

During its evolution JavaScript as a programming language went through a dramatic metamorphosis. From, so-called, “glue language”, “easy for non-software engineers language”, it became to be a de-facto industrial standard for web development and it expands its scope of influence and applications. Now it allows not just to manipulate with web page, but make an application like installable web apps, using input devices for HTML5 games with Gamepad API, develop native applications with React Native (another prominent example is Electron Framework which was used to create VS Code!), utilize Bluetooth capabilities within the browser with Web Bluetooth API. Also, it is even trying to overcome inborn low performance with a great project called WebAssembly. And of course, I can’t help by mentioning the coming of JS to the server as Node.js and his “brother” Deno js.

In this small summary, I would like to encourage beginners to get more familiar with cutting-edge JS. Also, I consider that experienced developers could find something new or recall something useful.

JS can control smart lamps… So what?

One could think that such notable moving out of language’s original scope can bring various troubles since language has not been developed, for example, hardware-related things, and going to have lack features. And it is true. However, JS on its way was not just solving (at least trying) its own issues but was getting some capabilities that overhead when things come to new types of tasks. To be able to utilize effectively those features and solve conventional routines more conveniently, it worth invest a little time into learning modern technics.

Essentials.

Frequently updates of language or whatever have incremental nature. That’s why I would like to establish some zero ground. First of all, with due respect, it will be fair to say that one of the foundation stones of modern JS is the Promise object. Seems trivial, but may confuse at first. For example


const promise1 = new Promise((resolve, reject) => {
console.log('A');
});
promise1.then().catch(); // promise call
console.log('B'); // next operation

It is crucial to understand that ‘B’ will appear in the console before ‘A’ even if Promise was called first. Also if a structure like (resolve, reject) => { /* promise code*/ } looks new, by all means, it is worth very important to become familiar with arrow functions (and why it is not 100% equal to simple function with its special this behaviour). By the way in that example arguments of arrow function (resolve, reject) are functions too and will be if promise fulfilled or rejected respectively. In its turn then() or catch() will be called. Usually, arrow functions are placed withing then catch handlers, so we have something like promise1.then((result) => {/* do something with result */}).catch((someError) => {/* oops, something went wrong, but at least we can check what someError can tell us */}). The full description can found here and there. Visiting adjacent sections is strongly recommended.  Similar to the knife that complements a fork,  async/await syntax complements promises.

Fresh updated & tricks from 2020.

JavaScript being a language with dynamic typing (and Duck typing) does not suppose to have rich types. For numbers, it has a type, who would have thought, the Number. It allows representing 64-bit floating-point numbers or integers with a maximum value of 2^53. When it is necessary to deal with 1) big numbers for complex calculations (a scientific-related example is there) or 2) interact with GUID or UUID even 2^53 may not be enough. In the second case, string representation can do the trick but not in the first for sure. Standard offers to use BigInt by adding to the end of literal. For example


const myBigFantasticNumber = 999999999999n;

or user constructor


const myBigFantasticNumber = BigInt("999999999999");

The price of this is paying attention to mixing types. It is prohibited to add Number and BigInt.  Explicit conversion of Number to BigInt is necessary (hello strict languages ).

The next update is globalThis. It happens that accessing a global object in different JS environments became to be different. In the browser context global object is the window, for instance, compatible browsers allow to access Bluetooth features through window.navigator.bluetooth. Web Workers that for example are used in PWA use the keyword self. Node.js environment uses the keyword global. And sort of special case with Vue.js, where this is access to a global variable (data) but within a component, so it’s not top level. It is possible to use some workarounds, but it adds unnecessary complexity and of course, it is error-prone practice.  To address this problem globalThis was implemented. Similar to goto mechanism that considered a bad practice but exists for the reason, overusing of the global item is not recommended as well.

Now something more interesting. Promises can be chained or fire simultaneously with Promise.all() by collecting them into an array before. It is even possible to fire several promises but if it’s enough to get any first fulfilled single result, Promise.race() should be used. Another obvious case, what if it is necessary to get at least something? In the case of Promise.all() has one reject, it will return just reject and no successful ones. Promise.allSettled() aimed to fill that gap.

The next update is a new operator that can be seen in other languages like Swift. It is nullish coalescing operator. For example, it is necessary to have back up for some uncertain value


const value = yourObj.uncertainValue || defaultValue;

Idea is to set up some value if uncertainValue is undefined or null. This mechanism will have false-positive cases when uncertainValue is false or ” “(nature of JS, nothing to do).

Extra code necessary for checking, but with an update, it’s enough to use


const value = yourObj.uncertainValue ?? defaultValue;

Now default value will be assigned only if uncertainValue is undefined or null.

The next similar operator allows doing optional chaining. In order to avoid the very popular error “Cannot read property something of undefined” usually the following code used:


const uncertainObject = getUncertainObjectFunction();
const value =  uncertainObject ? uncertainObject .something : undefined;

The new shorter syntax allow to write just


const value =  uncertainObject?.value;

It shines when you have nested uncertain structure like


const address = starSystem?.planet?.city?.homeAddress;

The same works with dynamic properties (which itself is a nice trick):


const value = uncertainObject?.["value"]; // instead of string "value" of course you can put variable

Or with functions:


const result = uncertainObject.uncertainFunction?.(); // If function is not defined we got undefined. 

Small things but they are actually optional game-changers.

Among other updates are some advanced mechanisms for importing and exporting modules like dynamic import which import something on demand and use memory when it’s really necessary. If the architecture of a project assumes to grow big and reuse code, it’s definitely worth checking that topic from its origins and come to recent standard updates.

Bonus advice

Keeping knowledge about standards can improve your coding skills,  but sometimes the target environment is too different from something that you run locally in your localhost:8080 (or something similar). Development tools in the browser usually allow imitating the screen size of a target device and some other features but it will only imitate real situation.

Some local development servers allow access within the local wifi network, but it’s not always an option, because of network security setting or remote workstyle which became trendy recently. One of the possible solutions which became to be very handy in my practice is ngrok. Online service allows deploying server which will have a tunnel to the local development environment. The free account is free so the speed is limited. However, I consider this as a good extra stress factor. The attentive reader immediately will ask “what about tests using some devices? How to see console?”, and its fair question. Fortunately, there is a solution that covers the case with an android mobile device. Having a device connected to a computer, open the special development tab of the Chrome browser and get a window that mirrors the devices browser screen which can be used for controlling the site on the device screen. What is more important is access to development tools including console. Unfortunately, the device should run Chrome browser. A similar method for sure exists for iOS devices and of course, it works withing Safari.

  • このエントリーをはてなブックマークに追加

Comments are closed.