Logesh Paul

Designer, Coder, Perfectionist

Javascript - Types

| Comments

Differences between undefined and null

  • undefined means a variable has not been declared, or has been declared but has not yet been assigned a value
  • null is an assignment value that means “no value”
  • Javascript sets unassigned variables with a default value of undefined
  • Javascript never sets a value to null. It is used by programmers to indicate that a var has no value.
  • undefined is not valid in JSON while null is
  • undefined typeof is undefined
  • null typeof is an object. Why?
  • Both are primitives
  • Both are falsy (Boolean(undefined) // false, Boolean(null) // false)

You can know if a variable is undefined

1
typeof variable === "undefined"

You can check if a variable is null

1
variable === null

The equality operator considers them equal, but the identity doesn’t

1
2
3
4
// equality
null == undefined // true
// identity
null === undefined // false

Using Array Concat to Create Effective Methods

| Comments

Rather than writing separate methods to handle an array and a single element parameter, write effective functions with help of concat so they can handle both. This is similar to how some of jQuery’s functions work (css will modify everything matched by the selector).

You just have to concat everything into an array first. Array.concat will accept an array or a single element.

1
2
3
4
5
6
function printUpperCase(words) {
  var elements = [].concat(words);
  for (var i = 0; i < elements.length; i++) {
    console.log(elements[i].toUpperCase());
  }
}

printUpperCase is now ready to accept a single node or an array of nodes as its parameter.

1
2
3
4
5
6
printUpperCase("Piano");
// => PIANO
printUpperCase(["guitar", "drums", "keyboard"]);
// => GUITAR
//  DRUMS
//  KEYBOARD

Javascript - Strings

| Comments

Sorting Strings

Javascript has a native method sort that allows sorting arrays. Doing a simple array.sort() each value will be treated as a string and sorted alphabetically. Also you can create your own custom sorting function passing it how argument.

1
2
['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort();
// ["Buenos Aires", "Mumbai", "New York", "Shanghai"]

But when you try order an array of non ASCII characters like this ['é', 'a', 'ú', 'c'], you will obtain an strange result ['c', 'e', 'á', 'ú']. That happens because sort works only with english language.

See the next example:

1
2
3
4
5
6
7
// Spanish
['único','árbol', 'cosas', 'fútbol'].sort();
// ["cosas", "fútbol", "árbol", "único"] // bad order

// German
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort();
// ["Wann", "Woche", "wäre", "wöchentlich"] // bad order

Fortunately exists two ways to avoid this mistake localeCompare and Intl.Collator provided by ECMAScript Internationalization API.

Both methods have his own custom parameters in order to configure it for work adequately.

Using localeCompare()

1
2
3
4
5
6
7
8
9
['único','árbol', 'cosas', 'fútbol'].sort(function (a, b) {
  return a.localeCompare(b);
});
// ["árbol", "cosas", "fútbol", "único"]

['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(function (a, b) {
  return a.localeCompare(b);
});
// ["Wann", "wäre", "Woche", "wöchentlich"]

Using Intl.Collator()

1
2
3
4
5
['único','árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare);
// ["árbol", "cosas", "fútbol", "único"]

['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare);
// ["Wann", "wäre", "Woche", "wöchentlich"]
  • For each method you can customize the location.
  • According Firefox Intl.Collator it’s more fast for compare large numbers of strings.

So remember when you are working with arrays of string in another language that not is english, use this methods to avoid unexpected errors.

ES6 Template Strings

As of ES6, JS now has template strings as an alternative to the classic end quotes strings.

Normal string

1
2
3
4
5
var firstName = 'John';
var middleName = 'Paul';
var lastName = 'Jones';
console.log('My name is ' + firstName + ' ' + middleName + ' ' + lastName);
// My name is John Paul Jones

Template String

1
2
3
4
5
var firstName = 'John';
var middleName = 'Paul';
var lastName = 'Jones';
console.log(`My name is ${firstName} ${middleName} ${lastName}`);
// My name is John Paul Jones

You can do Multi-line strings without \n and simple logic (ie 2+3) inside ${} in Template String.

You are also able to to modify the output of template strings using a function; they are called Tagged template strings for example usages of tagged template strings.

You may also want to read to understand template strings more

Javascript - Better Nested Conditionals With Objects

| Comments

How can we improve and make more efficient nested if statement on javascript.

1
2
3
4
5
6
7
8
9
10
11
12
13
if (color) {
  if (color === 'black') {
    printBlackBackground();
  } else if (color === 'red') {
    printRedBackground();
  } else if (color === 'blue') {
    printBlueBackground();
  } else if (color === 'green') {
    printGreenBackground();
  } else {
    printYellowBackground();
  }
}

One way to improve the nested if statement would be using the switch statement. Although it is less verbose and is more ordered, It’s not recommended to use it because it’s so difficult to debug errors, here’s why

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch(color) {
  case 'black':
    printBlackBackground();
    break;
  case 'red':
    printRedBackground();
    break;
  case 'blue':
    printBlueBackground();
    break;
  case 'green':
    printGreenBackground();
    break;
  default:
    printYellowBackground();
}

But what if we have a conditional with several checks in each statement? In this case, if we like to do less verbose and more ordered, we can use the conditional switch. If we pass true as parameter to the switch statement, It allows us to put a conditional in each case.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch(true) {
  case (typeof color === 'string' && color === 'black'):
    printBlackBackground();
    break;
  case (typeof color === 'string' && color === 'red'):
    printRedBackground();
    break;
  case (typeof color === 'string' && color === 'blue'):
    printBlueBackground();
    break;
  case (typeof color === 'string' && color === 'green'):
    printGreenBackground();
    break;
  case (typeof color === 'string' && color === 'yellow'):
    printYellowBackground();
    break;
}

But we must always avoid having several checks in every condition, avoiding use of switch as far as possible and take into account that the most efficient way to do this is through an object

1
2
3
4
5
6
7
8
9
10
11
var colorObj = {
  'black': printBlackBackground,
  'red': printRedBackground,
  'blue': printBlueBackground,
  'green': printGreenBackground,
  'yellow': printYellowBackground
};

if (color && colorObj.hasOwnProperty(color)) {
  colorObj[color]();
}

Another best example why to use objects for conditionals - link

Javascript - Array

| Comments

Array Manipulation

Insert an item into an existing array is a daily common task. You can add elements to the end of an array using push, to the beginning using unshift, or the middle using splice.

But those are known methods, doesn’t mean there isn’t a more performant way [or] maybe a faster way.

Add to end of an array
Add a element at the end of the array is easy with push(), but there is a way more performant.

1
2
3
4
var arr = [1,2,3,4,5];

arr.push(6);
arr[arr.length] = 6; // 43% faster in Chrome 47.0.2526.106 on Mac OS X 10.11.1

Both methods modify the original array. Don’t believe me? Check the jsperf

Add to beginning of an array
Now we are trying to add a item to the beginning of the array

1
2
3
4
var arr = [1,2,3,4,5];

arr.unshift(0);
[0].concat(arr); // 98% faster in Chrome 47.0.2526.106 on Mac OS X 10.11.1

Here is a little bit detail, unshift edit the original array, concat return a new array. jsperf

Add to middle of an array
Add items at the middle of an array is easy with splice and is the most performant way to do it.

1
2
var items = ['one', 'two', 'three', 'four'];
items.splice(items.length / 2, 0, 'hello');

Tried to run these tests in various Browsers and OS and the results were similar.

Next time you write you code don’t just check for the best way of writing your code but also write code which runs faster to improve performance.

Convert Nodelist to Array

The querySelectorAll method returns an array-like object called a node list. These data structures are referred to as “Array-like”, because they appear as an array, but can not be used with array methods like map and foreach.

Here’s a quick, safe, and reusable way to convert a node list into an Array of DOM elements:

1
2
3
4
5
6
7
8
const nodeList = document.querySelectorAll('div');
const nodeListToArray = Array.apply(null, nodeList);

//later on ..

nodeListToArray.forEach(...);
nodeListToArray.map(...);
nodeListToArray.slice(...);

The apply method is used to pass an array of arguments to a function with a given this value. MDN states that apply will take an array like object, which is exactly what querySelectorAll returns. Since we don’t need to specify a value for this in the context of the function, we pass in null or 0. The result is an actual array of DOM elements which contains all of the available array methods.

Alternate method if you are using ES2015 you can use the spread operator ...

1
2
3
4
5
6
7
const nodeList = [...document.querySelectorAll('div')]; // returns a real Array

//later on ..

nodeList.forEach(...);
nodeList.map(...);
nodeList.slice(...);

Empty an Array

You define an array and want to empty its contents. Usually, you would do it like this:

1
2
3
4
5
6
7
// define Array
var list = [1, 2, 3, 4];
function empty() {
    //empty your array
    list = [];
}
empty();

But there is another way to empty an array that is more performant.

You should use code like this:

1
2
3
4
5
6
var list = [1, 2, 3, 4];
function empty() {
    //empty your array
    list.length = 0;
}
empty();
  • list = [] assigns a reference to a new array to a variable, while any other references are unaffected. which means that references to the contents of the previous array are still kept in memory, leading to memory leaks.

  • list.length = 0 deletes everything in the array, which does hit other references.

In other words, if you have two references to the same array (a = [1,2,3]; a2 = a;), and you delete the array’s contents using list.length = 0, both references (a and a2) will now point to the same empty array. (So don’t use this technique if you don’t want a2 to hold an empty array!)

Think about what this will output:

1
2
3
4
5
6
7
8
9
var foo = [1,2,3];
var bar = [1,2,3];
var foo2 = foo;
var bar2 = bar;
foo = [];
bar.length = 0;
console.log(foo, bar, foo2, bar2);

// [] [] [1, 2, 3] []

Stackoverflow more detail: difference-between-array-length-0-and-array