A note on values and NaN

All values can be used in Boolean context and tested for truthiness. The values undefined, null, '', 0, [], false, and NaN (Not a Number) are falsy and all the other values are truthy.

NaN in particular is a special case and it does not behave like other real numeric values. NaN is toxic; any calculation that includes NaN will give a result of NaN. Furthermore, although NaN is falsy, it does not equal anything, including NaN itself. The usual way of checking for NaN is via the isNaN() function. If you find NaN lurking somewhere unexpected, you might give debugging log statements for code, leading to where you detected NaN; there may be some distance between where NaN was first generated and where you observed it corrupting your results.

Functions

In a function, by default, control flows from the beginning to the end, and the function returns undefined. Optionally, there can be a return statement before the end, and the function will stop execution and return the value in question. The following example illustrates a function with a return:

var add = function(first, second) {
  return first + second;
}

console.log(add(1, 2));

// 3

The previous function takes two parameters, although functions can be given (without an error or error message) fewer or more arguments than the declaration specifies. If they are declared to have values, those values will be present as local variables (in the preceding example, first and second). In any case, the arguments are also available in an array-like object called arguments which has a .length method (arrays have a .length method which is one greater than the highest position of an item), but not the rest of an array's features. Here we make a function that can take any arbitrary number of Number arguments, and returns their (arithmetical) average by using the arguments pseudo-array.

var average_arbitrarily_many() {
  if (!arguments.length) {
    return 0;
  }
  var count = 0;
  var total = 0;
  for(var index = 0; index < arguments.length; index += 1) {
    total += arguments[i];
  }
  return total / arguments.length;
}

Basic data types include number, string, Boolean, symbol, object, null, and undefined. Objects include function, array, date, and RegExp.

The fact that the objects include the functions means that the functions are values and can be passed as values. This facilitates higher-order functions, or functions that take functions as values.

For an example of a higher-order function, we will include a sort function that sorts an array and optionally accepts a comparator. This builds on function definitions, actually containing a function definition within a function definition (which is perfectly legal as anywhere else), and then an implementation of QuickSort where values are divided into compares as less than the first element, compares as equal to the first element, and compares as greater than the first element, and the first and last of these three are recursively sorted. We check for nonempty length before sorting, in order to avoid infinite recursion. An implementation of the classic QuickSort algorithm, here implemented as a higher-level function, is as follows:

var sort = function(array, comparator) {
  if (typeof comparator === 'undefined') {
    comparator = function(first, second) {
      if (first < second) {
        return -1;
      } else if (second < first) {
        return 1;
      } else {
        return 0;
      }
    }
  }
  var before = [];
  var same = [];
  var after = [];
  if (array.length) {
    same.push(array[0]);
  }
  for(var i = 1; i < array.length; ++i) {
    if (comparator(array[i], array[0]) < 0) {
      before.push(array[i]);
    } else if (comparator(array[i], array[0]) > 0) {
      after.push(array[i]);
    } else {
      same.push(array[i]);
    }
  }
  var result = [];
  if (before.length) {
    result = result.concat(sort(before, comparator));
  }
  result = result.concat(same);
  if (after.length) {
    result = result.concat(sort(after, comparator));
  }
  return result;
}

Explanation

There are several basic features and observations to note regarding this function, which is not intended to be pushing the envelope, but demonstrate how to cover standard bases well:

  1. We use var sort = function()... rather than the permitted function sort().... When used within a function, this stores the function in a variable, rather than defining something globally. Note that it may be helpful in debugging to include a name for the function, var sort = function sort()... to access the function only through the variable, and let debuggers pick up on the second. For example: sort rather than referring to the function anonymously. Note that with var sort = function(), the variable declaration is hoisted, not the initialization; with function sort(), the function value is hoisted, available anywhere within the current scope.
  2. This is a standard way of checking to see if only one of the two arguments has been specified, that is if an array has been provided without a sort function. If not, a default function is provided. We run a few trial runs of sorting:
    console.log(sort([1, 3, 2, 11, 9]));
    console.log(sort(['a', 'c', 'b']));
    console.log(sort(['a', 'c', 'b', 1, 3, 2, 11, 9]); 

    This gives us:

    [1, 2, 3, 9, 11]
    ["a", "b", "c"]
    ["a", 1, 3, 2, 11, 9, "b", "c"] 

    This gives us an opportunity to debug. Now, let's suppose we add the following:

    console.log('Before: ' + before);
    console.log('Same: ' + same);
    console.log('After: ' + after);

    Before the declaration of result, we get:

    [1, 2, 3, 9, 11]
    Before:
    Same: a
    After: c,b
    Before: b
    Same: c
    After: 
    Before:
    Same: b
    After:
    ["a", "b", "c"]
    Before:
    Same: a,1,3,2,11,9
    After: c,b
    Before: b
    Same: c
    After: 
    Before: 
    Same: b
    After:  
    ["a", 1, 3, 2, 11, 9, "b", "c"]

The output that says Same: a,1,3,2,11,9 looks suspicious, a Same bucket should have identical values, so that an appropriate output might be Same: 2,2,2 or just Same: 3 where the Same list has five values, no two of which are alike. This can't be the behavior we intended. It appears that the integers are being classified as the same as the initial "a", and the rest of it is being sorted. A little investigation confirms that '"a" < 1' and '"a" > 1' are both false, so our comparator could be improved.

We make a dictionary order sort of their types. This is somewhat arbitrary to sort first on alphabetical order of type, and then on the default sort order within types defaults which could be overridden with another comparator. This is an example of another of the many kinds of comparators one might use to sort an array: this one, unlike the previous one, segments different kinds of items such as Numbers sorted in order, and will appear before Strings, sorted in order:

        var comparator = function(first, second) {
          if (typeof first < typeof second) {
            return -1;
          } else if (typeof second < typeof first) {
            return -1;
          } else if (first < second) {
            return -1;
          } else if (second < first) {
            return 1;
          } else {
            return 0;
          }
        }

The typeof function returns a string containing a description of a type; thus typeof can offer an extended type. With a comparator function similar to this, one can meaningfully compare objects such as records that hold a first name, a last name, and an address.

Objects can be declared via curly brace notation. Blocks of code and objects can both use curly braces, but these are two separate things. The following code with its braces, is not a block of code with statements to execute; it defines a dictionary with keys and values:

var sample = {
  'a': 12,
  'b': 2.5
};

Unless a key is a reserved word or contains a special character, as 'strange.key' does (here a period), the quotation marks around a key are optional. JSON formatting, in order to have a simple and consistent rule, requires quotes in all cases, and specifically double quotes, not single.

An example of a record having a first name, a last name, and email address, perhaps populated via JSON, is shown next. This example is not JSON because it does not follow JSON's rules about double quoting all keys and all strings, but it illustrates an array of records which could have other fields and could be much longer. It may make sense to sort by distance or seniority (with populated fields not shown here): there is a whole world of possible comparators one might use for records.

var records = [{
    first_name: 'Alice',
    last_name: 'Spung',
    email: '[email protected]'
  }, {
    first_name: 'Robert',
    last_name: 'Hendrickson',
    email: '[email protected]'
  }
];

Note that a trailing comma is not merely inappropriate in JavaScript (after the last entry in almost anything separated by commas), but it has some strange and unexpected behavior which can be extremely hard to debug.

JavaScript was designed to have semicolons at the end of a statement which may be optional. This is a debatable decision, and was tied to a decision to make a popular language that regular non-programmers could use without involving IT people, a factor also involved in the design of SQL. We should always supply semicolons when they are appropriate. One side effect of this is that return alone on a line will return undefined. This means that the following code will not have the desired effect and will return undefined:

return
  {
  x: 12
  };

Note

The effect as the code is executed is different from what it appears to be and probably what was intended, so it is advisable to not do it.

To get the desired effect, the open curly brace should be on the same line as the return statement, as shown next:

return {
  x: 12
};

However, JavaScript does have an object-oriented programming that avoids a classical difficulty in object-oriented programming: having to get the ontology right the first time. Objects are usually best constructed, not as instances of a class, but by factories. Or so Douglas Crockford has been abbreviated. Prototypes are still part of the language, like many features good and bad, but barring esoteric use cases objects should usually be made by factories that allow for a "better than ontology-driven classes" approach to object-oriented programming. We will be avoiding the pseudo-classical new function(), not because it can clobber global variables if you ever forget the new, but because its semblance of traditional object-oriented programming does not really help that much.

Note

You should be aware of a wide-respected convention in JavaScript that constructors intending to work with new begin with a capital letter. If a function name begins with a capital letter, it is intended to be used with the new keyword, and strange things may happen if it is invoked without the new keyword.

In JavaScript, the interests served by classical object-oriented programming in some other languages are sometimes best advanced by functional programming.

Loops

Loops include the for loop, the for in loop, the while-do loop, and the do-while loop. The for loop works as in C:

var numbers = [1, 2, 3];
var total = 0;
for(var index = 0; index < numbers.length; ++index) {
  total += numbers[index];
}

The for in loop will loop over everything in an object. The hasOwnProperty() method can be used to examine only an object's fields. The two variants, for an object named obj, are as follows:

var counter = 0;
for(var field in obj) {
  counter += 1;
}

This will include any fields from the prototype chain(not explained here). To check things that are direct properties of an object itself, and not potentially noisy data from a prototype chain, we use an object's hasOwnProperty() method:

var counter = 0;
for(var field in obj) {
  if (obj.hasOwnProperty(field)) {
    counter += 1;
  }
}

Ordering is not guaranteed; if you are looking for any specific fields, it is worth considering to just iterate over the fields you want and check them on an object.

Loops

Taking a look at ECMAScript 6

JavaScript tools have been booming, with one tool being eclipsed by another and an incredibly rich ecosystem that few developers can boast knowing both broadly and deeply. However, the core language, ECMAScript or JavaScript, has been stable for several years.

ECMAScript 6, introduces profound new changes and expansions to the core language. As a rule, these features enhance, deepen, or make more consistent the functional aspects of JavaScript. It might be suggested that ECMAScript 6 features that do not do this kind of work, such as enhanced class-oriented syntactic sugar to let Java programmers pretend that JavaScript means programming in Java, may be ignored.

ECMAScript 6 features are a force to reckon with and at the time of this writing have more than started to make their way into the mainstream browsers. If you want to expand and improve your value as a JavaScript developer, don't restrict yourself to digging deeper into the rich JavaScript ecosystem, no matter how important that may be. Learn the new JavaScript. Part 3, Learning ECMAScript 6, will help you in getting started and working with ECMAScript 6.

Taking a look at ECMAScript 6
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.10.169