ikerhurtado.com
You're in
Iker Hurtado's pro blog
Developer | Entrepreneur | Investor
Software engineer (entrepreneur and investor at times). These days doing performant frontend and graphics on the web platform at Barcelona Supercomputing Center

Going deeply into Javascript. Basics (I): types, expressions, statements and operators

15 May 2015   |   iker hurtado  
Share on Twitter Share on Google+ Share on Facebook
In this post I write down some notes on basics of JavaScript language like types, expressions, statements and operators. It's not intended to be an exhaustive or complete resource about this issues.

Strict Mode

Starting from ECMAScript 5 version, strict mode is a way to opt in to a restricted variant of JavaScript. strict mode favors cleaner JavaScript, with fewer unsafe features, more warnings, and more logical behavior.

We can globally select strict mode on by typing the following line first in our JavaScript file or script element in HTML page:

'use strict';

In adittion, it's possible to switch on strict mode per function. This way:

function test() {
   'use strict';
   ...

Some features strict mode provides and force to do:

  • All variables must be explicitly declared
  • Functions must be declared at the top level of a scope (global scope or directly inside a function)
  • Stricter rules for function parameters
  • this is undefined in nonmethod functions
  • Illegal manipulations of properties throw exceptions

Expressions and Statements

An Javascript expression produces a value and can be written wherever a value is expected (i.e. an argument in a function call or at the right side of an assignment).

Conversely, a Javascript statement performs an action.

Wherever JavaScript expects a statement, it's also possible to write an expression -which is called expression statement. The reverse does not hold: it's not possible to write a statement where an expression is expected.

Function declaration vs function expression

It's worthy to be aware of this difference.

function test() { }

The previous construct could be either a named function expression or a function declaration. In order to prevent ambiguity during parsing, JavaScript does not let function expressions as statements. If an expression starts with function, it can only appear in an expression context.

JavaScript’s Types

JavaScript makes a somewhat arbitrary distinction between values:

  • The primitive values (booleans, numbers, strings, null and undefined)
  • All other values are objects

The main difference between the two is how they are compared; each object has a unique identity and is only equal to itself. In contrast, all primitive values encoding the same value are considered the same.

Primitive Values

Primitives have the following characteristics:

  • Compared by value: The “content”, not the element identity, is compared.
  • Always immutable: Properties can’t be changed, added, or removed.
  • A language set of types: It's not possible to define new primitive types.

Objects

All nonprimitive values are objects. The most common kinds of objects are:

  • Plain objects can be created by object literals. Example:
    {
      nane: 'Lucas',
      age: 34
    }
    
  • Arrays can be created by array literals. Their elements that can be accessed via numeric indices. Example:
    ['cat', 'dog', 'giraffe']
    
  • Regular expressions can be created by regular expression literals

Objects have the following characteristics:

  • Compared by reference: Object identities are compared
  • Mutable by default: It's possible to change, add, and remove object properties
  • Custom types: Constructors can be seen as implementations of custom types.

undefined and null

Javascript has two special values for nonvalue concept (missing information): undefined and null. The reason is historical.

There are some slight difference of meaning between them:

  • undefined means “no value” (neither primitive nor object). Uninitialized variables, missing parameters, and missing properties have that nonvalue. And functions implicitly return it if nothing has been explicitly returned.
  • null means “no object”. It is used as a nonvalue where an object is expected (as a parameter, as a member in a chain of objects, etc.).

Finally, undefined and null are the only values for which any kind of property access results in an exception. undefined is also sometimes used as more of a metavalue that indicates nonexistence. In contrast, null indicates emptiness.

Type Coercion

Type coercion refers to the implicit conversion of a value of one type to a value of another type. Most of JavaScript’s operators, functions, and methods coerce operands and arguments to the types that they need. So, this is a very important concept to keep in mind (JavaScript rarely complains about a value having the wrong type).

Operators

Operators and objects

All operators coerce their operands to appropriate types. Most operators only work with primitive values; therefore, objects are converted to primitives before being computed.

There is no way to overload or customize operators.

Equality Operators: === vs ==

JavaScript has two ways of determining whether two values are equal:

  • Strict equality (===) -and inequality (!==)- consider only values that have the same type to be equal.
  • Normal equality (==) -and inequality (!=)- try to convert values of different types before comparing them.

Normal equality is problematic and error prone due to type conversions. It is strongly recommended to use strict equality and avoid normal or lenient equality.

Strict equality

Two values with different types are never equal. If both values have the same type, then the following assertions hold:

  • undefined === undefined
  • null === null
  • Two numbers: x === x, +0 === -0 and “NaN” is not equal to itself.
  • Two objects (arrays and functions included): x === y if are the same object.

Equality results between booleans and strings are obvious.

Ordering Operators

JavaScript has the typical ordering operators (< , <= , > , >=) that work for numbers and for strings.

For strings, they are not very useful, because they are case-sensitive and don’t handle features such as accents well

This is the process these operators do to compare the operands:

1. Ensure that both operands are primitives. Objects are converted to primitives via the internal operation ToPrimitive(obj, Number).

2. If both operands are strings, then compare them by lexicographically comparing the 16-bit code units that represent the JavaScript characters of the string.

3. Otherwise, convert both operands to numbers and compare them numerically.

The + operator

First, it examines its operands. If one of them is a string, the other is also converted to a string and both are concatenated. Otherwise, both operands are converted to numbers and added. Examples:

> 3 + 'hello'
'3hello'

> 'Animals: ' + [ 'dog', 'cat', 'giraffe' ]
'Animals: dog,cat,giraffe'

typeof and instanceof

In order to categorize a value, first, we have to distinguish between primitives and objects.

The typeof operator distinguishes primitives from objects and determines the types of primitives. Unfortunately, the results of this operator are not completely logical and only loosely correspond to the types of the ECMAScript specification:

typeof of undefined or a undeclared variable -> 'undefined'
typeof of null -> 'object'
typeof of a Boolean value -> 'boolean'
typeof of a Number value -> 'number'
typeof of an String value -> 'string'
typeof of a function -> 'function'
All other normal values 'object'

The instanceof operator determines whether an object is an instance of a given constructor.

Logical Operators

- Binary Logical Operators: And (&&) and Or (||) work this way:

They always return either one of the operands, unchanged. Examples:

> 'hello' || 89
'hello'

> false || 'hello'
'hello'

- The second operand is not evaluated if the first operand already determines the result. That is uncommon behavior for operators. Normally, all operands are evaluated before an operator is invoked.

The behavior by operator is:

  • Logical And (&&): If the first operand can be converted to false, return it. Otherwise, return the second operand
  • Logical Or (||): If the first operand can be converted to true, return it. Otherwise, return the second operand.
  • Logical Not (!): The logical not operator ! converts its operand to boolean and then negates it.

Truthy and Falsy Values

Wherever JavaScript expects a boolean, any type of value is automatically converted to boolean. So, there are two sets of values in JavaScript: one set is converted to false (falsy values), while the other set is converted to true (truthy values).

The falsy values are (by types):

undefined and null
Boolean: false
Number: 0 , NaN
String: ''

All other values —including all objects (even empty objects), empty arrays, and new Boolean(false)— are truthy.

POST A COMMENT: