In the second part of this series, we learned about binary/octal literals and enhanced object literals. We also looked at different levels of support in JS environments. Since September this year, an important event has happenedthe merging of Node.js and io.js. Node.js is the community-led foundation and Joyent backed open source project. io.js is the community fork formed with the intention of having a truly community driven JS environment and bringing in ES6 features faster. Both groups have decided to merge and Node.js version 4.0 is the resultant combination. For a detailed insight into the significance of the merger, read the article in the first reference given at the end of this article.
Something good about what we are going to learn this month is that these features are supported in most common JS environments, i.e., Node.js 4.0+, Babel, Chrome 45 and Firefox 41.
Computed property keys
In JavaScript, an object is used to group variables into a collection. Typically, the creation of an object involves defining a set of properties and assigning default values. In addition, JavaScript has the capability of dynamically (after definition) adding and deleting properties on-the-fly. The property names at the time of definition are strings, which follow rules of definition of a variable and are fixed, as in the example below:
let point = { x: 10, y: 20, }
In ES6, JavaScript comes with the capability of defining property names as computed strings. This capability gives you programmatically defined property names that could change with each run and also adapt property names to the environment. Let us look at the various ways in which the property names can be computed:
1. let i = 0; 2. let std = ecma; 3. let fn = print; 4. 5. let obj = { 6. [js + ++i]: i, 7. [js + 2]: ++i, 8. [js + new Date().getFullYear()]: 10, 9. [std]: 20, 10. [fn]: function() { console.log(hello!); }, 11. }; 12. console.log(JSON.stringify(obj)); // {js1:1,js2:2,js2015:10,ecma:20} 13. obj.print(); // hello!
In the above code snippet, lines 6 to 10 have different ways in which the property name is computed. In line 6, we have created a property name concatenating a string with a variable value. In line 7, we have concatenated two strings. In line 8, we have part of the property name as the return value of a function. With such capabilities, the program can have property names change at the time of execution. The same program, run in 2016, will give the property name js2016. In line 10, we have an example of a function name computed from a variable substitution.
String functions
There are new string functions that will be part of the JavaScript language with effect from the ES6 version. They can be categorised into template functions and search functions, as shown in Table 1.
You can see in Table 1 that new functions are of two types – static and prototype. Static functions are available without an instance variable, whereas a prototype function should have a string instance. This will be clear in the following examples.
The String.raw function
This function is introduced along with template strings (refer to Part 1 of this series). Template strings allow variable substitution, and the interpretation of special characters like newline, tab, etc. During string operations, it is required to search or compare characters in the exact raw form instead of interpreted forms. The String.raw function keeps the string the same as what is seen by the programmer in the editor. In other words, \n is two characters \ and n.
String.raw is a static function, which means you do not need to have a string object created to use the function.
The raw function has two forms:
String.raw`template string` String.raw({ raw: string}, substitute_string)
Note: The first form does not have parenthesis like other functions. It is just a template string enclosed in back-ticks. In the second form the property name should be raw.
1. let year = 2015; 2. console.log(`osidays\t${year}`); //osidays 2015 3. console.log(String.raw`osidays \t${year}`); //osidays \t2015 4. console.log(String.raw({ raw: osi}, 1, 2)); //o1s2i 5. console.log(osi \uD83D\uDE80); //osi 6. console.log(String.raw`osi \uD83D\uDE80`); //osidays \uD83D\uDE80
To see the special characters in the above code snippet, please visit, http://www.es6fiddle.net/ifxcl0ay/.
Line 2 is an example of a template string. Line 3 displays the non-printable tab character in the raw form. Line 4 is the second form of a raw function where it takes two arguments. The first is the string parameter and the second is a substitution string. Line 5 prints special Unicode characters. In line 6, the same string with String.raw displays individual characters.
Finding string and repeat
New helper string functions introduced in ES6 are startsWith(), endsWith() and includes(). These three functions need objects to be created, before they can be used. They also take optional second parameters to indicate from which character position the find operation should start.
let str = osidays2015; console.log(str.startsWith(osi)); // true console.log(str.startsWith(si, 2)); // false console.log(str.endsWith(15)); // true console.log(str.endsWith(20)); // false console.log(str.includes(day)); // true
The next utility function is repeat(), which takes an argument and returns the same string count a number of times.
let pattern = =+=; console.log(pattern.repeat(5)); //=+==+==+==+==+= console.log(ab.repeat(5)); //ababababab
Number object extensions
The already existing global functions, isFinite(), isNaN(), parseFloat() and parseInt(), are now added to the Number object. This groups related functions under the Number object. One difference we should be aware of is that the global function automatically converts a number in the string form to a number, whereas when used with the Number object, it does not. The following example makes this clear:
console.log(Number.isFinite(3)); // true console.log(Number.isFinite(3)); // false console.log(isFinite(3)); // true
In addition to functions, there are three properties added to the Number object. They are: EPSILON, MIN_SAFE_INTEGER and MAX_SAFE_INTEGER.
JavaScript stores numbers as floating point numbers internally. Arithmetic operations may not yield the desired results due to a difference in small precision. For example, 0.21+0.2 !== 0.41 due to precision error.
The Number.EPSILON is the smallest interval between two representable numbers. Its value is 2.220446049250313e-16.
To overcome precision errors, Number.EPSILON is used. When a math operation is performed, check if the resultant difference is more than Number.EPSILON. As we are aware, JavaScript has number representation that is in the range of 2-53 and 2+53.
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991 console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
The new properties help in checking the valid range after mathematical computations. There is a function isSafeInteger() that checks if a number is within valid range.
console.log(Number.isSafeInteger(42342343434343)); // true console.log(Number.isSafeInteger(232342342343434343)); // false
Installing Node.js 4.1.1 in Ubuntu
It is important if you have migrated to the latest Node.js environment to try ES6 features. The following two steps will get you to the latest version. If yours is not an Ubuntu environment, please refer to the Node.js home page.
curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - sudo apt-get install -y nodejs
Staying up-to-date
If you are interested in learning more about JavaScript, take a look at Table 2, which features a few influential people you should follow.
Next month we will learn about the for..of iterator which can be used on strings and collection data structures like arrays. We will also learn about a shorthand notation called arrow functions.
References
[1] io.js and Node.js Have United and Thats a Good Thing– http://thenewstack.io/io-js-and-node-js-have-united-and-thats-a-good-thing/
[2] Detailed list of JS environments support: http://kangax.github.io/compat-table/es6/
[3] Try ES6 features online http://www.es6fiddle.net/