Categories
JavaScript JavaScript Basics

The Comprehensive List of JavaScript String Methods

Strings are an important global object in JavaScript. They represent a sequence of characters. They can be used by various operators, like comparison operators, and there are various methods that can be used to manipulate them. There are different ways to manipulate strings, look up parts of a string in various positions, and trim and replace strings. With each release of the JavaScript specification, more methods are added to make string search and manipulating easier than ever.


Static Methods

Static methods are called without having to create a string literal or object. There are the following methods:

String.fromCharCode()

With the fromCharCode method, we can construct a string by passing in a comma-separated list of HTML character codes or the hexadecimal Unicode character code as arguments and get a string with the actual characters returned. For example, we can write:

const str = String.fromCharCode(38, 8226)

Then, we get &• when we log str with console.log. We can pass in hexadecimal character codes, like in the following code:

const str = String.fromCharCode(0x0026, 0x2022)

Then, we also get &• when we log str with console.log.

String.fromCodePoint()

The String.fromCodePoint() method returns a string given by the character codes that you entered into the arguments. The code points can be HTML character codes or the hexadecimal Unicode character code. For example, we can write:

const str = String.fromCodePoint(38, 8226)

Then, we get &• when we log str with console.log. We can pass in hexadecimal character codes, like in the following code:

const str = String.fromCodePoint(0x0026, 0x2022)

Then, we also get &• when we log str with console.log.


Instance Methods

Instance methods of a string are called on the string literal or the string object. They do something to the instance of the string that’s being called on.

String.prototype.charAt()

charAt returns the character located at the index of the string.

For example:

const str = "Hello";  
const res = str.charAt(0); // 'H'

String.charCodeAt()

charCodeAt returns the UTF-16 character code located at the index of the string.

For example:

const str = "Hello";  
const res = str.charCodeAt(0); // 72

String.prototype.codePointAt()

codePointAt returns the code point value of the UTF-16 encoded code point located at the index of the string.

For example:

const str = "Hello";  
const res = str.codePointAt(0); // 72

String.prototype.concat()

The concat method combines two strings and returns a new string. For example, we can write:

const str1 = "Hello";  
const str2 = " World";  
const res = str1.concat(str2); // 'Hello World'

String.prototype.endsWith()

endsWith checks if a string ends with the substring you passed in.

For example:

const str = "Hello world.";  
const hasHello = str.endsWith("world."); // trueconst str2 = "Hello world.";  
const hasHello2 = str.endsWith("abc"); // false

String.prototype.includes()

includes checks if the passed-in substring is in the string. It returns true if it’s in the string, and false otherwise.

const str = "Hello";  
const hasH = str.includes('H'); // true  
const hasW = str.includes('W'); // false

String.prototype.indexOf()

indexOf finds the index of the first occurrence of the substring. It returns -1 if not found.

For example:

const str = "Hello Hello.";  
const hasHello = str.indexOf("Hello"); // 0  
const hasHello2 = str.indexOf("abc"); // -1

String.lastIndexOf()

lastIndexOf finds the index of the last occurrence of the substring. It returns -1 if not found.

For example:

const str = "Hello Hello.";  
const hasHello = str.lastIndexOf("Hello"); // 6  
const hasHello2 = str.lastIndexOf("abc"); // -1

String.prototype.localeCompare()

The localeCompare method compares whether one string comes before another by using the locale’s rules for comparing the order of precedence of the string. The general syntax to call this method is:

referenceStr.localeCompare(compareString, locales, options)

It returns the following values depending on whether referenceStr comes before compareStr:

  • Negative when the referenceStr occurs before compareStr
  • Positive when the referenceStr occurs after compareStr
  • Returns 0 if they are equivalent

The first argument of the method is the string you want to compare with.

The second argument of the method optionally takes a locale string or an array of locale strings, which are BCP-47 language tag with optional Unicode extension keys. Unicode extension keys, including "big5han", "dict", "direct", "ducet", "gb2312", "phonebk", "phonetic", "pinyin", "reformed", "searchjl", "stroke", "trad", and "unihan" are also allowed in our locale strings. They specify the collations that we want to compare strings with. However, when there are fields in the options in the second argument that overlap with this, then the options in the argument overrides the Unicode extension keys specified in the first argument.

Numerical collations can be specified by adding kn to your locale string in your first argument. For example, if we want to compare numerical strings, then we can write:

console.log('10'.localeCompare('2', 'en-u-kn-true'));

Then, we get one since we specified kn in the locale string in the constructor. This makes the collator compare numbers, and 10 comes after two.

Also, we can specify whether upper or lowercase letters should be sorted first with the kf extension key. The possible options are upper, lower, or false. false means that the locale’s default will be the option. This option can be set in the locale string by adding it to the locale string as a Unicode extension key, and if both are provided then the option property will take precedence. For example, to make uppercase letters have precedence over lowercase letters, we can write:

console.log('Able'.localeCompare('able', 'en-ca-u-kf-upper'));

This will sort the same word with uppercase letters first. When we run console.log, we get -1 since we have an uppercase ‘A’ in ‘Able,’ and a lowercase ‘a’ for ‘able.’ On the other hand, if we instead pass in en-ca-u-kf-lower in the constructor, like in the code below:

console.log('Able'.localeCompare('able', 'en-ca-u-kf-lower'));

Then after console.log we get one because kf-lower means that we sort the same word with lowercase letters before the ones with uppercase letters.

The third argument of the method optionally takes an object that can have multiple properties. The properties that the object accepts are localeMatcher, usage, sensitivity, ignorePunctuation, numeric, and caseFirst. numeric is the same as the kn option in the Unicode extension key in the locale string, and caseFirst is the same as the kf option. The localeMatcher option specifies the locale matching algorithm to use. The possible values are lookup and best fit. The lookup algorithm searches for the locale until it finds the one that fits the character set of the strings that are being compared. best fit finds a locale that is possibly more suited than the lookup algorithm.

The usage option specifies whether the Collator is used for sorting or searching for strings. The default option is sort.

The sensitivity option specifies the way that the strings are compared. The possible options are base, accent, case, and variant. base compares the base of the letter, ignoring the accent. For example, a is not the same as b, but a is the same as á, and a is the same as Ä . accent specifies that a string is only different if their base letter or their accent is unequal, ignoring case. So, a isn’t the same as b, but a is the same as A. a is not the same as á.

The case option specifies that strings that are different in their base letters or case are considered unequal, and so a wouldn’t be the same as A and a wouldn’t be the same as c, but a is the same as á. variant means that strings that have different base letters, accents, other marks, or cases are considered unequal. For example, a wouldn’t be the same as A and a wouldn’t be the same as c, but a also wouldn’t be the same as á.

The ignorePunctuation specifies whether punctuation should be ignored when sorting strings. It’s a boolean property and the default value is false.

String.prototype.match()

The match method retrieves the substring matches of a string given the regular expression to match with. The match method takes a regular expression as an argument. It can either be a regular expression literal or a RegExp object. If no regular expression is given, we’ll get an array with an empty string. If the regular has the g flag, then all the matches in a string will be returned in the array. Otherwise, only the first will be returned.

The matches are returned as an array. For example, we can do a case insensitive search with the i flag:

const str = 'foo';  
const re = /foo/i;  
const found = str.match(re);  
console.log(found);

If we run the code above, we get:

[  
  "foo"  
]

from the console.log statement above.

If we toggle the g flag on and off, we get different results. If the regular has the g flag, then all the matches in a string will be returned in the array. Otherwise, only the first will be returned. If we have the g flag on like in the code below:

const str = 'The quick brown fox jumps over the lazy dog. It barked.';  
const globalRe = /[A-Z]/g;  
const globalFound = str.match(globalRe);  
console.log(globalFound);  
console.log(JSON.stringify(globalFound, (key, value) => value, 2));

Then we get:

[  
  "T",  
  "I"  
]

from the console.log statement above. However, if we removed the g flag, like in the code below:

const re = /[A-Z]/;  
const found = str.match(re);  
console.log(found);  
console.log(JSON.stringify(found, (key, value) => value, 2));

Then we get:

[  
  "T"  
]

from the console.log statement above.

String.prototype.matchAll()

The matchAll method would return all the results that are found by passing in a regular expression to the argument of the matchAll method. It returns an iterator with arrays of the result as the array entries. For example, if we have the following code to do a global search:

const str = 'The quick brown fox jumps over the lazy dog. It barked.';  
const globalRe = /[A-Z]/g;  
const globalFound = [...str.matchAll(globalRe)];  
console.log(globalFound);  
console.log(JSON.stringify(globalFound, (key, value) => value, 2));

Then we get:

[  
  [  
    "T"  
  ],  
  [  
    "I"  
  ]  
]

On the other hand, if we don’t have the global flag in the regular expression to do a global search, like in the following code:

const re = /[A-Z]/;  
const found = [...str.matchAll(re)];  
console.log(found);  
console.log(JSON.stringify(found, (key, value) => value, 2));

Then we get:

[  
  [  
    "T"  
  ]  
]

from the console.log statement above.

String.prototype.normalize()

The normalize method returns the Unicode Normalization Form of a given string. It will convert non-string arguments into a string before conversion. For example, if we have:

const first = '\u00e5'; // "å"
const second = '\u0061\u030A'; // "å"

Then we call the normalize method in each string to normalize them into the same character code:

first.normalize('NFC') === second.normalize('NFC')

The code above will evaluate to true since we normalized the strings to the same character code. However, if we didn’t call normalize:

first === second

Then the code above would return false . If we run console.log on both strings to get their character codes like in the code below:

console.log(first.normalize('NFC').charCodeAt(0));
console.log(second.normalize('NFC').charCodeAt(0));

We get 229 for the first characters for both strings since they’re the same after normalization. On the other hand, if we run it before normalization with normalize like in the code below:

console.log(first.charCodeAt(0));
console.log(second.charCodeAt(0));

We get that the first string logs 229 and the second logs 97.

String.prototype.padStart()

The padStart() function pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start of the current string.

The function takes 2 parameters. The first is the target length of your string. If the target length is less than the length of your string, then the string is returned as-is. The second parameter is the string that you want to add the padding with. It’s an optional parameter and it defaults to ' ' if nothing is specified.

For example, we can write the following:

'def'.padStart(10);         // "       def"
'def'.padStart(10, "123");  // "1231231def"
'def'.padStart(6,"123465"); // "abcdef"
'def'.padStart(8, "0");     // "00000def"
'def'.padStart(1);          // "def"

Note that each string is filled up to the target length with the string in the second argument. The whole string in the second argument may not always be included. Only the part that lets the function fills the string up to the target length is included.

String.prototype.padEnd()

The padEnd() function pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the end of the current string.

The function takes 2 parameters. The first is the target length of your string. If the target length is less than the length of your string, then the string is returned as-is. The second parameter is the string that you want to add the padding with. It’s an optional parameter and it defaults to ' ' if nothing is specified.

For example, we can write the following:

'def'.padEnd(10);         // "def       "
'def'.padEnd(10, "123");  // "def1231231"
'def'.padEnd(6,"123465"); // "defabc"
'def'.padEnd(8, "0");     // "def00000"
'def'.padEnd(1);          // "def"

String.prototype.repeat()

To use the repeat function, you pass in the number of times you want to repeat the string as an argument. It returns a new string.

For example:

const hello = "hello";
const hello5 = A.repeat(5);
console.log(hello5); // "hellohellohellohellohello"

String.prototype.replace()

The replace() function included with strings is useful for replacing parts of strings with another. It returns a new string with the string after the substring is replaced.

Example:

const str = "Hello Bob";
const res = str.replace("Bob", "James"); // 'Hello James'

replace() can also be used to replace all occurrences of a substring.

For example:

const str = "There are 2 chickens in fridge. I will eat chickens today.";
const res = str.replace(/chickens/g, "ducks"); // "There are 2 chickens in fridge. I will eat chickens today."

If the first argument is a regular expression that searches globally, it will replace all occurrences of the substring.

String.search()

search gets the position of the substring passed into the function. It returns -1 if the substring is not found in the string.

Example:

const str = "Hello";
const res = str.search('H'); // 0

String.prototype.slice()

The slice method extracts a part of the string and returns a new string. We can pass in both positive and negative numbers. If the range is positive, then the returned substring will start and end with the indexes that are passed in. If they’re negative, then the starting index starts from the last character of the string with index -1 and then count backward back to the start of the string, going down by 1 when a character is left of another character. If the second argument is omitted, then it’s assumed to be the index of the last character of the string.

For example, we can write:

const str = 'Try not to become a man of success. Rather become a man of value.';
console.log(str.slice(31));
// output: "ess. Rather become a man of value."console.log(str.slice(4, 19));
// output: "not to become a"console.log(str.slice(-4));
// output: "lue."console.log(str.slice(-9, -5));
// output: "of v"

String.prototype.startsWith()

startsWith checks if a string starts with the substring you pass in.

For example:

const str = "Hello world.";
const hasHello = str.startsWith("Hello"); // trueconst str2 = "Hello world.";
const hasHello2 = str.startsWith("abc"); // false

String.prototype.split()

The split method splits a string into an array of substrings. The split method can split a string using a regular expression as the delimiter. For example, we can write:

const str = 'The 1 quick 2 brown fox jump.';
const splitStr = str.split(/(\d)/);console.log(splitStr);
// gets \["The ", "1", " quick ", "2", " brown fox jump."\]

This splits a sentence into an array of strings with the numbers separating the words. It can also take a string as the delimiter for separating the string like in the following example:

const str = 'The 1 quick 2 brown fox jump.';
const splitStr = str.split(' ');console.log(splitStr);
// gets \["The", "1", "quick", "2", "brown", "fox", "jump."\]

It can also take an array of strings as separators of the given string instance. For example:

const str = 'The 1 quick 2 brown fox jump.';
const splitStr = str.split(\[' '\]);
console.log(splitStr);
// gets \["The", "1", "quick", "2", "brown", "fox", "jump."\]

String.prototype.substr()

JavaScript strings have a substr function to get the substring of a string.

It takes a starting index as the first argument and a number of characters from the start index, and so on as the second argument.

It can be used like this:

const str = "Hello Bob";
const res = str.substr(1, 4); // ello

String.prototype.substring()

JavaScript strings also has a substring function that takes the start and end index as two arguments and returns a string with the ones between the start and end indices.

The start index is included but the end index is excluded.

Example:

const str = "Hello Bob";
const res = str.substring(1, 3); // el

<img alt="" class="t u v lu aj" src="https://miro.medium.com/max/1400/0*4SZwSC2Q8P8AoyXU" width="700" height="1050" srcSet="https://miro.medium.com/max/552/0*4SZwSC2Q8P8AoyXU 276w, https://miro.medium.com/max/1104/0*4SZwSC2Q8P8AoyXU 552w, https://miro.medium.com/max/1280/0*4SZwSC2Q8P8AoyXU 640w, https://miro.medium.com/max/1400/0*4SZwSC2Q8P8AoyXU 700w" sizes="700px" role="presentation"/>

Photo by Allef Vinicius on Unsplash

String.prototype.toLocaleLowerCase()

Converts a string to lowercase, according to the locale of your browser. The new string is returned instead of modifying the original string.

For example:

const str = "Hello Bob!";
const res = str.toLocaleLowerCase(); // hello bob!

String.prototype.toLocaleUpperCase()

Converts a string to uppercase, according to the locale of your browser. The new string is returned instead of modifying the original string.

For example:

const str = "Hello Bob!";
const res = str.toLocaleUpperCase(); // 'HELLO BOB!'

String.toLowerCase()

Converts a string to lowercase. The new string is returned instead of modifying the original string.

For example:

const str = "Hello Bob!";
const res = str.toLocaleLowerCase(); // 'hello bob!'

String.prototype.toUpperCase()

Converts a string to uppercase. The new string is returned instead of modifying the original string.

For example:

const str = "Hello Bob!";
const res = str.toLocaleUpperCase(); // 'HELLO BOB!'

String.prototype.trim()

Remove starting and ending white space from a string.

For example:

const str = "         Hello Bob!     ";
const res = str.trim(); // 'Hello Bob!'

String.prototype.trimStart()

Now the string object has a trimStart() function to trim the beginning whitespace of a string. There’s also a trimLeft() method which is an alias to this method.

For example, we can write:

let message = '   Hi! How\'s it going?   ';console.log(message);// We get '   Hi! How's it going?   'let message = '   Hi! How\'s it going?   ';
console.log(message.trimStart());// We get 'Hi! How's it going?   '

As we can see, the whitespace on the left side is gone. We can do the same thing with trimLeft() :

let message = '   Hi! How\'s it going?   ';
console.log(message.trimLeft());// We get 'Hi! How's it going?   '

Note that a new string is returned with trimStart or trimLeft, so the original string stays intact. This prevents us from mutating the original string, which is handy for preventing mistakes from accidentally mutating objects.

String.prototype.trimEnd()

The trimEnd method removes whitespace from the right end of the string. trimRight is an alias of the trimEnd method. For example, we write:

let message = '   Hi! How\'s it going?   ';
console.log(message);
// We get '   Hi! How's it going?   'let message = '   Hi! How\'s it going?';
console.log(message.trimEnd());
// We get '   Hi! How\'s it going?'

Note that a new string is returned with trimEnd or trimRight, so the original string stays intact. This prevents us from mutating the original string, which is handy for preventing mistakes from accidentally mutating objects.

String.valueOf()

With the valueOf method, we can convert a string object into a primitive string. For example, we can write:

const sPrim = 'foo';
const sObj = new String(sPrim);
console.log(typeof sPrim);
console.log(typeof sObj.valueOf());

Then we get that both console.log statements would show ‘string’.

Conclusion

Strings are an important global object in JavaScript. It represents a sequence of characters. It has methods to manipulate strings, look up parts of a string in various positions, and trim and replace strings. With each release of the JavaScript specification, more methods are added to make string search and manipulating easier than ever.

Categories
JavaScript JavaScript Basics

Great New Features in ES2018 You May Have Missed

Ever since ES2015 was released, which was a great leap forward in itself, JavaScript has been improving at a fast pace. Every year since then, new features have been added to JavaScript specifications.

Features like new syntax and new methods for building in JavaScript have been added consistently. In ES2016 and 2017, The Object object had methods like Object.values and Object.entries added.

String methods like padStart and padEnd were added in ES2017. async and await, which is a shorthand syntax for chaining promises, were also added in ES2017.

The includes methods for arrays were added in ES2016. ES2018 was another release with lots of new features. With ES2018, the spread syntax is now available for object literals. Rest parameters were also added.

The for await...of loop, which is a loop syntax iterating through promises sequentially, was also added. The SharedArrayBuffer object was added for representing raw binary data that cannot become detached.

A finally function was also added to the Promise object.


Spread Operator in Objects

The spread syntax works by copying the values of the original array, and then inserting them into another array or putting them in the order they appeared in the array as the list of arguments in a function in the same order.

When the spread operator is used with objects, the key-value pairs appear in the same order they appeared in the original object.

With ES2018, the spread operator works with object literals. Then key-value pairs of an object can be inserted into another object with the spread operator.

If there are two objects with the same key that the spread operator is applied to in the same object, the one that’s inserted later will overwrite the one that’s inserted earlier.

For example, if we have the following:

let obj1 = {foo: 'bar', a: 1};  
let obj2 = {foo: 'baz', b: 1};  
let obj3 = {...obj1, ...obj2 }

Then we get {foo: “baz”, a: 1, b: 1} as the value of obj3 because obj1 is spread before obj2. They both have foo as a key in the object.

First foo: 'bar' is inserted by the spread operator to obj3. Then foo: 'baz' overwrites the value of foo after obj2 is merged in since it has the same key, foo, but was inserted later.

This is great for merging objects as we don’t have to loop through the keys and put in the values, which is much more than one line of code.

One thing to note is that we can’t mix the spread operator between regular objects and iterable objects. For example, we will get TypeError if we write the following:

let obj = {foo: 'bar'};  
let array = [...obj];

Rest Operator

The rest operator is a JavaScript operator where we can store an indefinite number of arguments in a function as an array. It looks exactly like the spread operator, which lets us spread entries of an array or a list of key-value pairs of an object into another object.

For example, if we have a function that has a long list of arguments, we can use the rest operator to shorten the list of parameters in a function.

The rest operator is used with the following syntax:

const fn = (a,b,..restOfTheArgs) => {...}

Where restOfTheArgs is an array with the list of arguments other than the first two.

For example, if we want to write a sum function that takes an indefinite list of numbers as arguments and sum up the numbers, we can write:

const sum = (a,b,...otherNums) => {  
  return a + b + otherNums.reduce((x,y)=>x+y, 0);  
}

As we can see, this is very handy for functions that have any list of arguments. Before we had this, we had to use the arguments object available in functions to get a list of arguments. This is not ideal as we allow them to pass in anything into the arguments.

With the rest operator, we have the best of both worlds. We can have some fixed parameters, while the rest stay flexible. This makes functions more flexible than functions with a fixed number of parameters, while having some flexibility of functions that take an indefinite number of arguments.

The arguments object has all the arguments of the function. Also, it’s not a real array, so array functions aren’t available to them. It’s just an object with indexes and keys to denote the argument’s positions.

Methods like sort, map, forEach, or pop cannot be run on the argument’s object. It also has other properties. This creates confusion for programmers. The arguments that are converted to an array with the rest operator do not have these issues, as they are real arrays.

To call the sum function we wrote, we can write:

const result = sum(1,2,3,4,5,6,7,8,9,10);

The result will be 55, since we summed up all the arguments together. otherNums is an array with all the numbers other than 1 and 2.

We can also use the rest operator to destructure a list of arguments into a list of variables. This means that we can convert a list of parameters into an array with the spread operator, and then decompose the array of arguments into a list of variables.

This is very useful as we can get the entries of the array that’s operated on by the rest operator and convert them to named variables. For example, we can write:

const sum = (a,b,...[c,d,e])=> a+b+c+d+e;

This way, we can use the rest operator, but limit the number of arguments that your function accepts. We take the function parameters a and b, and we also take c, d, and e as parameters.

However, it’s probably clearer without using the rest operator since all the parameters are fixed, we can just list the parameters directly.


for await...of

The for await...of loop allows us to create a loop that iterates over a list of promises as well as over the entries of a normal iterables.

It works with iterable objects like arrays, string, argument object, NodeList object, TypedArray, Map, Set, and user-defined synchronous and asynchronous iterable objects.

To use it, we write:

for await (let variable of iterable) {  
  // run code on variable
}

The variable may be declared with const, let, or var, and the iterable is the iterable objects that we are iterating over. We can iterate over asynchronous iterable objects like the following:

const asynNums = {  
  [Symbol.asyncIterator]() {  
    return {  
      i: 6,  
      next() {  
        if (this.i < 20) {  
          return Promise.resolve({  
            value: this.i++,  
            done: false  
          });  
        }
        return Promise.resolve({  
          done: true  
        });  
      }  
    };  
  }  
};

(async () => {  
  for await (let num of asynNums) {  
    console.log(num);  
  }  
})();

We should see 6 to 19 logged. It also works with async generators:

async function* asynNumGenerator() {  
  var i = 6;  
  while (i < 20) {  
    yield i++;  
  }  
}

(async () => {  
  for await (let num of asynNumGenerator()) {  
    console.log(num);  
  }  
})();

We should see the same thing logged. It also works great with promises:

const arr = Array.from({  
  length: 20  
}, (v, i) => i)let promises = [];

for (let num of arr) {  
  const promise = new Promise((resolve, reject) => {  
    setTimeout(() => {  
      resolve(num);  
    }, 100)  
  })  
  promises.push(promise);  
}

(async () => {  
  for await (let num of promises) {  
    console.log(num);  
  }  
})();

As we can see, if we run the code above, we should see 0 to 19 logged sequentially, which means that promises were iterated through in sequence. This is very handy as we never have anything that can iterate through asynchronous code before this loop syntax was introduced.


Promise.finally()

The finally function is added to the Promise object which runs when the promise is settled. That means it runs whenever the promise is fulfilled or rejected.

It takes a callback function that runs whenever the promise is settled. This lets us run code regardless of how a promise ends. Also, this means that we no longer have to duplicate code in the callbacks for then and catch functions.

To use the finally function, we use it as the following:

promise  
.finally(()=>{  
  // run code that when promise is settled  
})

The finally is useful is we want to run code whenever a promise ends like cleanup code or processing after the code ends.

It’s very similar to calling .then(onFinally, onFinally). However, we do not have to declare it twice to make a variable for it and pass it in twice. The callback for the finally function doesn’t take any argument, as there’s no way to determine the status of the promise beforehand.

It’s used for cases when we don’t know what will happen to the promise, so there’s no need to provide any argument. If a promise is fulfilled then the resolved value will be intact after calling the finally function.

For example, if we have:

Promise.resolve(3).then(() => {}, () => {})

This will resolve to undefined, but if we have:

Promise.resolve(3).finally(() => {})

The code above will resolve to 3. Similarly, if the promise if rejected, we get:

Promise.reject(5).finally(() => {})

This will be rejected with the value 5.


SharedArrayBuffer

The SharedArrayBuffer is an object that’s used to represent a fixed-length raw binary data buffer.

It’s similar to the ArrayBuffer object, but we can use it to create views on shared memory. It can’t become detached, unlike an ArrayBuffer. The constructor of it takes the length of the buffer as an argument.

The length is the size in byte for the array buffer to create. It returns a SharedArrayBuffer of the specified size with contents initialized to 0.

Shared memory can be created and updated by multiple workers on the main thread. However, this may take a while until the changes are propagated to all contexts.


Conclusion

With ES2018, we have more handy features to help developers develop JavaScript apps.

The highlights include the spread operator for objects, which let us copy key-value pairs to other objects and the rest operator to let us pass optional arguments.

The for await...of loop lets us iterate through collections of asynchronous code which could never easily be done before.

Categories
JavaScript JavaScript Basics

How to Get the Length of An Object

There are 2 ways to get the length of the list of keys of an object.

Object.keys

Object.keys gets the top level list of keys of an object and returns an array of them. For example:

const a = {foo: 1, bar: 2};  
const length = Object.keys(a).length // 2

Object.getPropertyNames

Object.getPropertyNames also gets a list of all top level of keys of an object and return them as an array. For example:

const a = {foo: 1, bar: 2};  
const length = Object.getOwnPropertyNames(a).length // 2

for…in Loop

There is a special loop for looping through the keys of an object. You can do the following:

const a = {foo: 1, bar: 2};  
let keysCount = 0;  
for (let key in a) {  
    keysCount++;  
}  
console.log(keysCount) // 2
Categories
JavaScript JavaScript Basics

Formatting Dates With the DateTimeFormat Object

Different parts of the world have different date formats. To deal with this, JavaScript has the Intl.DateTimeFormat constructor to let us format dates into different formats according to different locales.

This means that we can format dates for different places without manipulating date strings ourselves, making our lives much easier. The Intl.DateTimeFormat constructor takes a locale string as the argument.

With the DateTimeFormat constructed with the constructor, we can use the format instance method, which takes in a Date object to return a date string with the date formatted for the locale you specified in the Intl.DateTimeFormat constructor.


The Constructor and the Format Method

To use the Intl.DateTimeFormat constructor, we can use it like in the following example:

const date = new Date(2019, 0, 1, 0, 0, 0);  
console.log(new Intl.DateTimeFormat('en-US').format(date));  
console.log(new Intl.DateTimeFormat('fr-ca').format(date));  
console.log(new Intl.DateTimeFormat(['ban', 'de']).format(date));

In the above example, we created the Date object, and then we used the Intl.DateTimeFormat constructor with one or more locales passed in as a string.

Then, we called format by passing in the Date object. The first example would log 1/1/2019 since the United States use the MM/DD/YYYY date format.

The second example would log 2019–01–01 since French Canadian dates are in YYYY-MM-DD format. The third example takes an array where there are multiple locales, the ones further to the right are the fallback locales for the ones for the left.

In our example, since we have an invalid locale string ban in the first entry of the array, we use the German date format de instead, to format the Date object, so we get 1.1.2019 since Germany uses the DD.MM.YYYY date format.

As we can see from the examples above, the Intl.DateTimeFormat constructor takes a locale string or an array of locale strings. It also accepts Unicode extension keys for locale strings, so that we can append them to our language tag.

The extension keys nu for setting the numbering system, ca for the calendar to format the date, and hc for the hour cycle are supported.

nu’s possible values can be arab, arabext, bali, beng, deva, fullwide, gujr, guru, hanidec, khmr, knda, laoo, latn, limb, mlym, mong, mymr, orya, tamldec, telu, thai, tibt.

ca’s possible values include buddhist, chinese, coptic, ethiopia, ethiopic, gregory, hebrew, indian, islamic, iso8601, japanese, persian, roc.

hc’s possible values include h11, h12, h23, h24. For example, to format dates according to the Buddhist calendar, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0);  
console.log(new Intl.DateTimeFormat('en-US-u-ca-buddhist').format(date));

Then we get 1/1/2562 in the console.log since the Buddhist calendar’s year 0 is at 545 BC.

The second argument takes an object that lets us set various options in its properties to format the date.

The localeMatcher option specifies the locale-matching algorithm to use. The possible values are lookup and best fit. The lookup algorithm searches for the locale until it finds the one that fits the character set of the strings that are being compared.

best fit finds the locale that is at least, but possibly more, suited than the lookup algorithm. The timeZone option lets us set the time zone which formats the date.

The most basic implementation only recognizes UTC, but others may recognize IANA time zone names in the IANA time zone data database, like Asia/Shanghai, Asia/Kolkata, America/New_York.

The hour12 option specifies whether the format is for 12-hour time or 24-hour time. The default is locale dependent. It overrides the hc language tag in the first argument.

It’s a true or false value where true means format the date time with 12-hour time. The hourCycle option has possible values of h11, h12, h23, h24 and overrides the hc language tag. hour12 takes precedence over this option if it’s specified.

The formatMatcher property specifies the matching algorithm to use. Possible values are basic and best fit. best fit is the default value.

The following subsets of the date time are required to match the date object to the correct format:

  • weekday, year, month, day, hour, minute, second
  • weekday, year, month, day
  • year, month, day
  • year, month
  • month, day
  • hour, minute, second
  • hour, minute

weekday represents the weekday value, possible values are:

  • long (e.g., Friday)
  • short (e.g., Fri)
  • “narrow" (e.g., T). Note that two weekdays may have the same narrow style for some locales. For example, Tuesday‘s narrow style is also T.

era represents the era, possible values are:

  • long (e.g., Anno Domini)
  • short (e.g., AD)
  • narrow (e.g., A)

year represents the year. The possible values are:

  • numeric (e.g., 2019)
  • 2-digit (e.g., 19)

month is the representation of the month. The possible values are:

  • numeric (e.g., 2)
  • 2-digit (e.g., 02)
  • long (e.g., February)
  • short (e.g., Feb)
  • narrow (e.g., M). Note that two months may have the same narrow style for some locales (e.g. May‘s narrow style is also M).

day represents the day. Possible values are:

  • numeric (e.g., 2)
  • 2-digit (e.g., 02)

hour is the representation of the hour. The possible values are numeric, 2-digit.

minute is the representation of the minute. The possible values are numeric, 2-digit.

second is the representation of the second. The possible values are numeric, 2-digit.

timeZoneName is the representation of the time zone name. The possible values are:

  • long (e.g., Pacific Standard Time)
  • short (e.g., GMT-8)

The default value for each component property above is undefined, but if all components are undefined then the year, month, and day are assumed to be numeric.

An example for using the options is below:

const date = new Date(2019, 0, 1, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric'  
};  
console.log(new Intl.DateTimeFormat('en-ca', options).format(date));

In the code above, we set the locale to Canadian English, and in the options object we set weekday to long, year to numeric, month to long, and day to numeric, so that we get the full weekday name in English, year as a number, month with the full name, and day as a number.

The console.log will log “Tuesday, January 1, 2019”. The example above can have a time zone added to it, as in the following example:

const date = new Date(2019, 0, 1, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric',  
  timeZone: 'America/Vancouver',  
  timeZoneName: 'long'  
};  
console.log(new Intl.DateTimeFormat('en-ca', options).format(date));

In the example above, we added the timeZone and timeZoneLong so that we get the time zone displayed, so that we get “Tuesday, January 1, 2019, Pacific Standard Time”.

The Intl.DateTimeFormat constructor handles non-English format equally well. For example, if we want to format a date into Chinese, we can change the locale and keep the options the same as above like in the following code:

const date = new Date(2019, 0, 1, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric',  
  timeZone: 'America/Vancouver',  
  timeZoneName: 'long'  
};  
console.log(new Intl.DateTimeFormat('zh-Hant', options).format(date));

Then, we get “2019年1月1日 星期二 太平洋標準時間”, which is the same as “Tuesday, January 1, 2019, Pacific Standard Time” in traditional Chinese.


Other Instance Methods

Instances of the Intl.DateTimeFormat constructor object also have a few instance methods in addition to the format() method.

It also has the formatToParts() method to return an array of objects representing different parts of the date string. The resolvedOptions() method returns a new object with properties that reflect the locale and formatting options that we computed during the initialization of the object.

The formatRange() method accepts two Date objects as arguments and formats the date range in the most concise way, based on the locale and options provided when we instantiate the DateTimeFormat object.

Finally, it has the formatRangeToParts() method which accepts two Date objects as arguments and formats the date range in the most concise way based on the locale and options provided when we instantiate the DateTimeFormat object and return the date time parts in an array of objects.

For example, if we have the following code that calls the formatRangeToParts() method:

const startDate = new Date(2019, 0, 1, 0, 0, 0);  
const endDate = new Date(2019, 0, 2, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric',  
  timeZone: 'America/Vancouver',  
  timeZoneName: 'long'  
};  
const dateRange = new Intl.DateTimeFormat('zh-Hant', options).formatRangeToParts(startDate, endDate)  
console.log(dateRange);

Then we get the following date and time parts logged:

[  
  {  
    "type": "year",  
    "value": "2019",  
    "source": "startRange"  
  },  
  {  
    "type": "literal",  
    "value": "年",  
    "source": "startRange"  
  },  
  {  
    "type": "month",  
    "value": "1",  
    "source": "startRange"  
  },  
  {  
    "type": "literal",  
    "value": "月",  
    "source": "startRange"  
  },  
  {  
    "type": "day",  
    "value": "1",  
    "source": "startRange"  
  },  
  {  
    "type": "literal",  
    "value": "日 ",  
    "source": "startRange"  
  },  
  {  
    "type": "weekday",  
    "value": "星期二",  
    "source": "startRange"  
  },  
  {  
    "type": "literal",  
    "value": " ",  
    "source": "startRange"  
  },  
  {  
    "type": "timeZoneName",  
    "value": "太平洋標準時間",  
    "source": "startRange"  
  },  
  {  
    "type": "literal",  
    "value": " – ",  
    "source": "shared"  
  },  
  {  
    "type": "year",  
    "value": "2019",  
    "source": "endRange"  
  },  
  {  
    "type": "literal",  
    "value": "年",  
    "source": "endRange"  
  },  
  {  
    "type": "month",  
    "value": "1",  
    "source": "endRange"  
  },  
  {  
    "type": "literal",  
    "value": "月",  
    "source": "endRange"  
  },  
  {  
    "type": "day",  
    "value": "2",  
    "source": "endRange"  
  },  
  {  
    "type": "literal",  
    "value": "日 ",  
    "source": "endRange"  
  },  
  {  
    "type": "weekday",  
    "value": "星期三",  
    "source": "endRange"  
  },  
  {  
    "type": "literal",  
    "value": " ",  
    "source": "endRange"  
  },  
  {  
    "type": "timeZoneName",  
    "value": "太平洋標準時間",  
    "source": "endRange"  
  }  
]

As we can see from the console output above, we get the date and time parts in each entry of the array, with the parts of the startDate coming first and the endDate parts being in the latter parts of the array.

If we call the formatRange() method, like in the code below:

const startDate = new Date(2019, 0, 1, 0, 0, 0);  
const endDate = new Date(2019, 0, 2, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric',  
  timeZone: 'America/Vancouver',  
  timeZoneName: 'long'  
};  
const dateRange = new Intl.DateTimeFormat('en', options).formatRange(startDate, endDate)  
console.log(dateRange);

Then we get:

"Tuesday, January 1, 2019, Pacific Standard Time – Wednesday, January 2, 2019, Pacific Standard Time"

From the console.log.

To call the resolvedOptions method, we can write the code below:

const date = new Date(2019, 0, 1, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric',  
  timeZone: 'America/Vancouver',  
  timeZoneName: 'long'  
};  
const resolvedOptions = new Intl.DateTimeFormat('en', options).resolvedOptions(date)  
console.log(resolvedOptions);

Then we get the options that we passed in for formatting the date back:

{  
  "locale": "en",  
  "calendar": "gregory",  
  "numberingSystem": "latn",  
  "timeZone": "America/Vancouver",  
  "weekday": "long",  
  "year": "numeric",  
  "month": "long",  
  "day": "numeric",  
  "timeZoneName": "long"  
}

In the console.log.

To use the formatToParts() method, we can use it like the format() method, like in the following code:

const date = new Date(2019, 0, 1, 0, 0, 0);  
const options = {  
  weekday: 'long',  
  year: 'numeric',  
  month: 'long',  
  day: 'numeric',  
  timeZone: 'America/Vancouver',  
  timeZoneName: 'long'  
};  
const dateParts = new Intl.DateTimeFormat('en', options).formatToParts(date)  
console.log(dateParts);

Then we get the parts of the formatted date in the console.log like in the output below:

[  
  {  
    "type": "weekday",  
    "value": "Tuesday"  
  },  
  {  
    "type": "literal",  
    "value": ", "  
  },  
  {  
    "type": "month",  
    "value": "January"  
  },  
  {  
    "type": "literal",  
    "value": " "  
  },  
  {  
    "type": "day",  
    "value": "1"  
  },  
  {  
    "type": "literal",  
    "value": ", "  
  },  
  {  
    "type": "year",  
    "value": "2019"  
  },  
  {  
    "type": "literal",  
    "value": ", "  
  },  
  {  
    "type": "timeZoneName",  
    "value": "Pacific Standard Time"  
  }  
]

As we can see, the Intl.DateTimeFormat constructor is very useful for formatting dates for different locales. It eliminates a lot of hassle when formatting dates.

The constructor takes one or more locales as the first argument and a variety of options as the second argument.

It can format dates into one string and also format them and break them up into parts. This saves a lot of hassle when formatting dates for different regions since we don’t have to do any date string manipulation.

Categories
JavaScript JavaScript Basics

Handling Dates in JavaScript

Handling date and time are also important in many JavaScript programs. This is why JavaScript has a built-in Date object to handle manipulating dates. Dates objects contain a number that represents the milliseconds since January 1970 in UTC (the Linux epoch time).

We can do a lot of things with the Date object to manipulate dates. However, it has many quirks and missing functionality. Therefore, third-party libraries are better with handling dates than using the built-in Date object in many cases. Moment.js is one of the more popular ones, so it’s naturally it is the first choice when we need to manipulate dates in JavaScript.

Built in Date Object

To work with dates in JavaScript, we have to create a new Date object. The constructor for the date object takes zero or more arguments. When there are no arguments passed in, then Date object created will have the current date and time in your local time zone, as of the time of instantiation.

The parameters it can accept include a date string, another date object, or the (years, month index, day, hour, minutes, seconds, and milliseconds) together. We can pass in a date string as follows to the date constructor:

new Date('2019-01-01');

If we log the result, we get ‘Mon Dec 31 2018 16:00:00 GMT-0800 (Pacific Standard Time)’ since the date is stored in UTC and the browser is running on a computer in the Pacific Time Zone, which is 8 hours behind UTC at January 1, 2019 is when Pacific Standard Time.

As we can see, passing a date string to the Date constructor is confusing. Different browsers will parse date strings differently. Likewise, the Date.parse method also shouldn’t be used to parse date strings. We can see that date-only strings like the one we passed in are treated as UTC and not local time.

If we want to pass in a Date object to the constructor we can write:

new Date(new Date());

We get something like ‘Sun Oct 20 2019 10:57:58 GMT-0700 (Pacific Daylight Time)’ when we log the result. This is shown in your local time.

We can pass in the year, month index, day, hour, minutes, seconds, and milliseconds into the constructor. Only year and month are required. So we can write something like:

new Date(2019,0,1,0,0,0,0)

This will return ‘Tue Jan 01 2019 00:00:00 GMT-0800 (Pacific Standard Time)’ if we log it. Note that we have 0 in the second argument of the constructor. The second argument is the month index, which is 0 for January, 1 for February, and so on. So December would be 11. The rest of the arguments are what we expect. The first is the year, the third is the day, the fourth is hours, the fifth is minutes, 6th is seconds, and the last one is milliseconds.

We can convert a Date object to the UNIX timestamp, which is the number of milliseconds since January 1, 1970 UTC with the unary + operator, so if we write:

+new Date(2019,0,1,0,0,0,0)

We get 1546329600000 when we log the output because it coerces the date to a number.

Another way to get the timestamp is by using the .getTime() method.

To alter the individual components of a Date object like setting the hours or day or getting components of a Date like the day of the week or day of the month, there are methods to do that in a Date object.

Methods in the Date Object

There are methods in the Date object to get and set parts of dates, and convert time to UTC, or set time zone offset. Some important Date object methods include the following:

Date.now()

Returns the current time in the form of a UNIX timestamp with leap seconds ignored. This method is static.

Date.UTC()

Returns the current time in the form of a UNIX timestamp with leap seconds ignored. This method is static. It accepts the same arguments as the longest list of arguments for the Date constructor which is year, month index, day, hour, minutes, seconds, and milliseconds, but only year and month are required. We can use it as in the following code:

Date.UTC(2019,0,1,1,0,0,0)

Which we return something like 1546304400000.

Getter Functions

Date.getDate()

Returns the day of the month according to local time. For example, if we have:

const date = new Date(2019,0,1,0,0,0,0);  
console.log(date.getDate());

We would get 1 since we specified it as the day of the month in the constructor’s arguments.

Date.getDay()

Returns the day of the week (0–6) for the specified date according to local time, where 0 represents Sunday and 6 represents Saturday and 1 to 5 represents the days in between. For example, we can write:

const date = new Date(2019,0,1,0,0,0,0);  
console.log(date.getDay());

Then we get 2, which is Tuesday.

Date.getFullYear()

Returns the 4 digit year of the specified date according to local time. For example, we can write:

const date = new Date(2019,0,1,0,0,0,0);  
console.log(date.getFullYear());

Then we get 2019, which is the 4 digit year of date.

Date.getHours()

Return the hour (0–23) of the specified date according to local time. For example, we can write:

const date = new Date(2019,0,1,0,0,0,0);  
console.log(date.getHours());

Then we get 0 which is what we specified in the hours argument in the constructor.

Date. getMilliseconds()

Returns the milliseconds of the specified date from 0 to 999 according to local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getMilliseconds());

This gets the milliseconds specified in the date object, which should return 0 as we specified in the constructor.

Date.getMinutes()

Returns the minute (0–59) of the specified date in local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getMinutes());

Then we get 0 minutes as we specified in the constructor.

Date.getMonth()

Returns the month (From 0 for January to 11 for December) of the specified date according to local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getMonth());

Then we get month 0 for January as we specified in the constructor.

Date.getSeconds()

Returns the seconds (0–59) in the specified date in local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getSeconds());

Then we get 0 seconds as we specified in the constructor.

Date.getTime()

Returns the UNIX timestamp for the specified date, which is the number of milliseconds since January 1, 1970 00:00:00 UTC. For prior times, it will be negative. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getTime());

Then we get 1546329600000 returned from the getTime() function. A shorthand for this is to use the unary + operator, like in the following code:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(+date);

If we run the code above, we get the same result logged.

Date.getTimezoneOffset()

Return time zone offset in minutes for the current location set on your host device. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getTimezoneOffset());

Then we get 480 if your host device is set to the Pacific Time Zone, since on January 1, 2019, the Pacific Time Zone is 8 hours behind UTC, so we get that the time zone offset is 480 minutes, which is 8 hours.

Date.getUTCDate()

Returns the day of the month, from 1 to 31, in the specified date according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCDate());

We get 1 since we specified January 1, 2019 as the date.

Date.getUTCDay()

Return the day of the week from 0 to 6 according to the specified date in UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCDay());

Then we get 2 because January 1, 2019 is Tuesday.

Date.getUTCFullYear()

Return the 4 digit year in the specified date according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCFullYear());

We get 2019 since this is what we specified in the date constructor.

Date.getUTCHours()

Return the hours from 0 to 23 in the specified date according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCHours());

If the locale setting is set to the Pacific Time Zone, we get 8 since we specified that the hour is 0 in local time which is the same as 8 in UTC on January 1, 2019.

Date.getUTCMilliseconds()

Returns the milliseconds of the specified date from 0 to 999 according to UTC. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCMilliseconds());

This gets the milliseconds specified in the date object, which should return 0 as we specified in the constructor.

Date.getUTCMonth()

Return the month from 0 for January to 11 for December in the specified time according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCMonth());

This gets the month specified in the date object, which should return 0 like we specified in the constructor.

Date.getUTCSeconds()

Returns the seconds (0–59) in the specified date in UTC. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCSeconds());

Then we get 0 seconds as we specified in the constructor.

Date.getYear()

Returns the year, which is usually 2 to 3 digits in the specified date according to the local time zone.

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
console.log(date.getUTCSeconds());

Then we get 119 for 2019.

If we instead have:

const date = new Date(1900, 0, 1, 0, 0, 0, 0);  
console.log(date.getYear());

We get 0 for 1900. And if we have:

const date = new Date(2000, 0, 1, 0, 0, 0, 0);  
console.log(date.getYear());

Then we get 100 for 2000. So 1900 is year 0 according to the getYear() method. It’s much better to use the getFullYear() method instead of getting the correct year from a Date object.

Setter Functions

There are also corresponding setter functions for each of the getter functions we mentioned above. We have the following setter functions for the Date object:

Date.setDate()

Sets the day of the month according to local time. For example, if we have:

const date = new Date(2019,0,1,0,0,0,0);  
date.setDate(2)  
console.log(date);

We would get ‘Wed Jan 02 2019 00:00:00 GMT-0800 (Pacific Standard Time)’ when the host device is set to the Pacific Time Zone since we specified 2 in the setDate function.

Date.setFullYear()

Sets the 4 digit year of the specified date according to local time. For example, we can write:

const date = new Date(2019,0,1,0,0,0,0);  
date.setFullYear(2020)  
console.log(date.getFullYear());

Then we get 2020, which is the 4 digit year of date.

Date.setHours()

Sets the hour (0–23) of the specified date according to local time. For example, we can write:

const date = new Date(2019,0,1,0,0,0,0);  
date.setHours(3)  
console.log(date.getHours());

Then we get 3 when we call getHours which is what we specified in the hours argument in the setHours function.

Date. setMilliseconds()

Sets the milliseconds of the specified date from 0 to 999 according to local time. For example, we can write:

const date = new Date(2019,0,1,0,0,0,0);  
date.setMilliseconds(3)  
console.log(date.getMilliseconds());

This sets the milliseconds specified in the date object, which should return 3 as we specified in the setMilliseconds function when we call the getMilliseconds function.

Date.setMinutes()

Sets the minute (0–59) of the specified date in local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setMinutes(20)  
console.log(date.getMinutes());

Then we get 20 minutes returned from getMinutes() like we specified in the setMinutes function.

Date.setMonth()

Sets the month (From 0 for January to 11 for December) of the specified date according to local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setMonth(3)  
console.log(date.getMonth());

Then we get month 3 returned from getMonth() after we set it by setMonth()

Date.setSeconds()

Sets the seconds (0–59) in the specified date in local time. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setSeconds(10);  
console.log(date.getSeconds());

Then we get 10 seconds from getSeconds() like we specified in the setSeconds function.

Date.setTime()

Sets the UNIX timestamp for the specified date, which is the number of milliseconds since January 1, 1970 00:00:00 UTC. For prior times, it will be negative. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setTime(100)  
console.log(date.getTime());

Then we get 100 returned from the getTime() function since we set it to 100 with setTime .

Date.setUTCDate()

Sets the day of the month, from 1 to 31, in the specified date according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setUTCDate(2)  
console.log(date.getUTCDate(2));

We get 2 since we specified 2 in setUTCDate

Date.setUTCFullYear()

Sets the 4 digit year in the specified date according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setUTCFullYear(2020)  
console.log(date.getUTCFullYear());

We get 2020 with getUTCFullYear() since this is what we specified in the date setUTCFullYear() function.

Date.setUTCHours()

Sets the hours from 0 to 23 in the specified date according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setUTCHours(2)  
console.log(date.getUTCHours());

We get 2 with getUTCHours() since we specified it when we call setUTCHours().

Date.setUTCMilliseconds()

Sets the milliseconds of the specified date from 0 to 999 according to UTC. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setUTCMilliseconds(10)  
console.log(date.getUTCMilliseconds());

This gets the milliseconds with getUTCMilliseconds(), which should return 10 as we specified in the setUTCMilliseconds().

Date.setUTCMonth()

Return the month from 0 for January to 11 for December in the specified time according to UTC. For example, if we write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setUTCMonth(3);  
console.log(date.getUTCMonth());

This gets the month specified in the date object, which should return 3 from getUTCMonth() like we specified in the setUTCMonth() call.

Date.setUTCSeconds()

Sets the seconds (0–59) in the specified date in UTC. For example, we can write:

const date = new Date(2019, 0, 1, 0, 0, 0, 0);  
date.setUTCSeconds(10);  
console.log(date.getUTCSeconds());

Then we get 10 seconds when we called getUTCSeconds() since we specified in 10 when we called setUTCSeconds().

The setYear() method set the ye. It’s much better to use the setFullYear() method instead for getting the correct year from a Date object.

The Date object has a few limitations. For example, it doesn’t support time zones. This creates problems when we need time zones data in our dates. JavaScript dates only supports the local time zone, UTC, or time zone offsets relative to UTC. Only some of the conversions between these time zones are allowed when manipulating date objects. For example, when we convert Date objects to a date string, we can only choose between local time and UTC. The JavaScript Date object stores dates in UTC internally.

Moment.js

Manipulating time and date in JavaScript is painful because of the limitations that we discussed above. Even with the functions available with Date objects, there are plenty of chances for bugs and errors. Also, there are no functions for formatting times and dates which is a big problem. To solve this, we use moment.js. This is the best library available for dealing with time.

The native JavaScript Date objects have issues with time zones with YYYY-MM-DD dates being parsed into UTC time as opposed to local time. This creates bugs for developers who aren’t aware of this problem. See https://stackoverflow.com/questions/29174810/javascript-date-timezone-issue

Also there are differences in support for parts of Dates in different browsers. (See https://stackoverflow.com/questions/11253351/javascript-date-object-issue-in-safari-and-ie)

It is also hard to add and subtract timestamps with the built-in Date functions. There is no way to do this without writing a lot of code and doing a lot of checks. Also, there is no way to compare 2 times.

Formatting dates is also not available without writing your own code for using third party libraries.

Moment.js solves all of these issues by providing built-in functions to do all these common operations. It provides functions for parsing and formatting dates.

The moment constructor is where you can pass in a date string, and a moment object will be created. For example, you can pass in:

moment('2019-08-04')

You will get back a moment which you can compare with other moment objects, and add or subtract by different time spans.

If you do not pass in anything to the moment constructor, you get the current date and time.

It also takes a second argument. If you want to make sure a date is parsed as a YYYY-MM-DD date, then write moment(‘2019–08–04’, 'YYYY-MM-DD'). If you don’t know the format of your date or time, then you can pass in an array of possible formats and Moment will pick the right one:

moment('2019–08–04', ['YYYY-MM-DD', 'DD-MM-YYYY']);

After you create a Moment object, then you can do many things like formatting dates:

const a = moment('2019–08–04', 'YYYY-MM-DD').format('MMMM Do YYYY, h:mm:ss a');  
console.log(a);// August 4th 2019, 12:00:00 am

const b = moment('2019–08–04', 'YYYY-MM-DD').format('dddd');  
console.log(b);// Sunday

const c = moment('2019–08–04', 'YYYY-MM-DD').format("MMM Do YY");  
console.log(c);// Aug 4th 19

const d = moment('2019–08–04', 'YYYY-MM-DD').format('YYYY [escaped] YYYY');      
console.log(d);// 2019 escaped 2019

const e = moment('2019–08–04', 'YYYY-MM-DD').format();  
console.log(e);// 2019-08-04T00:00:00-07:00

From the above examples, we see that we can format dates in pretty much any way we want.

We can also tell what time span a date is relative to another date by writing:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');  
const sepDate = moment('2019–09–04', 'YYYY-MM-DD');  
console.log(augDate.from(sepDate)); // a month ago

We can also add or subtract Moment dates:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');  
const sepDate = moment('2019–09–04', 'YYYY-MM-DD');  
console.log(augDate.add(10, 'days').calendar()); // 08/14/2019  
console.log(augDate.subtract(10, 'days').calendar()); // 07/25/2019

It is easy to compare 2 dates:

moment('2010-01-01').isSame('2010-01-01', 'month'); // true  
moment('2010-01-01').isSame('2010-05-01', 'day');   // false, different month  
moment('2008-01-01').isSame('2011-01-01', 'month'); // false, different year

You can also check if a date has Daylight Saving Time in effect or not:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');  
const decDate = moment('2019–12–04', 'YYYY-MM-DD');  
console.log(augDate.isDST()) // true  
console.log(decDate.isDST()) // false

And you can convert back to JavaScript date any time by calling the toDate() function on a Moment object.

As we can see, JavaScript’s Date object has limited capabilities when it comes to manipulating dates. It also doesn’t parse dates very well and has no ability for formatting dates easily. This is why we need to use libraries like Moment.js to fill in the gaps so we can create bug-free code that manipulates dates much more easily.