Javascript - The Good Parts by Douglas Crockford

1. Good Parts

  • built on some good ideas and bad ones
    • Good : functions, loose typing, dynamic objects, and an expressive object literal notation.
    • Bad : a programming model based on global variables
  • Javascript's functions are first class objects with lexical scoping. It is Lisp in C's clothing. This makes Javascript a remarkably powerful language.
  • Strong typing does not eliminate the need for the careful testing. Loose typing to be liberating. I don't need to form complex class hierarchies.

2. Grammar

Whitespace

Names

  • one or more letters, digits, or under bars
  • No use of reserved words

Numbers

  • only one number type
  • 64bit floating point as same as Java's double
  • no integer type, so 1 and 1.0 are the same value
  • NaN is not equal to any value, including itself. You should use isNaN() function

Strings

  • Some methods
    • toUpperCase()

Statements

  • the falsy values
    • false
    • null
    • undefined
    • The empty string ''
    • The number 0
    • The number NaN

Expressions

  • The || operator return the value of operand which is truthy.

Literals

  • Types
    • number literal
    • string literal
    • object literal
    • array literal
    • function
    • regexp literal

Functions

  • It has an optional name

3. Objects

Object literal

var empty_object = {};
 
var stooge = {
    "first-name": "Jerome",
    "last-name": "Howard"
};

var flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
}, arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    } 
};

Retrieval

  • The . notation is preferred for readability.
stooge["first-name"]            // "Joe"
flight.departure.IATA           // "SYD"

stooge["middle-name"]           // undefined
flight.status                       // undefined
stooge["FIRST-NAME"]            // undefined

var middle = stooge["middle-name"] || "(none)";
  • undefined will throw a TypeError exception. This can be guarded against wit the && operator.
flight.equipment                                    // undefined
flight.equipment.model                          // throw "TypeError"
flight.equipment && flight.equipment.model  // undefined

Reference

  • Objects are passed around by reference. They are never copied.

Prototype

  • Every object is linked to a prototype object from which it can inherit properties.
  • All objects created from object literals are linked to Object.prototype
  • If the object lacks the property name, then Javascript attempts to retrive the property value from the prototype obejct.
  • If the desired property exists nowhere in the prototype chain, then the result is the undefined value.
  • The proto property of Object.prototype is an accessor property. It is deprecated in favor of Obejct.getPrototypeOf()
var s = {"one": 123};
var a = Object.create(s);
// var a = Object.create(s.);
var b = Object.create(a);
b.another = 456;
var c = Object.create(b);

c.__proto__;
c.__proto__.__proto__;

c.one = 1;

Reflection

  • The typeof operator can be helpful in determining the type of property.
typeof flight.number            // 'number'
typeof flight.status            // 'string'
typeof flight.toString          // 'function'

flight.hasOwnProperty('number')     // true
flight.hasOwnProperty('constructor')    // false

Enumeration

  • The for in statement can loop over all of the property names in an object.
  • No guarantee on the order of the names
for (var name in flight) {
    if (typeof flight[name] !== 'function') {
        console.log(name + " : " + flight[name]);
    }
}

Delete

  • The delete operator can be used to remove a property from an object.
  • It will not touch any of the objects in the prototype linkage.
delete c.one;               // true

c.one;

delete c.one;               // true

c.one;

4. Functions

The best thing about Javascript is its implementation of functions. They are used for code reuse, information hiding, and composition.

Function Objects

  • Functions in Javascript are objects.
  • Objects are collecitons of name/value pairs having a hidden link to a prototype object.
  • Function objects are linked to Function.prototype.
  • Every function is created with two additional hidden properties(context, code).
  • Every function obejct is created with a prototype property. Its value is an object with a constructor property whose value is the function.
  • Used like any other value
    • Stored in vairables, objects and arrays
    • Passed as arguments to functions
    • A return value from funtions
    • Function can have methods
  • The thing that is special is that they can be invoked.

Function Literal

  • Function objects are created with function literals
  • The function name is optional, it used to call recursively itself.
var variable = function() {
    // body
}; // this is a function literal.
  • The function object created by a function literal contains a link to that outer context. This is called closure. This is the source of enormous expressive power.

Invocation

  • Every function recevives two additional parameters: this and arguments
  • No runtime error when the number of arguments and the number of parameters do not match
  • No type checking on the argument values
  • The this value is determined by following cases.
The Method Invocation Pattern
  • When a function is stored as a property of an object, we call it a method.
  • When a method is invoked, this is bound to that obejct.
  • If a refinemnet, it is invoked as a method.
 var myObject = {
         value: 0,
         increment: function (inc) {
             this.value += typeof inc === 'number' ? inc : 1;
} };
myObject.increment( ); 
document.writeln(myObject.value);           // 1
myObject.increment(2);
document.writeln(myObject.value);           // 3
  • This very late binding makes functions that use this highly reusable.
The Function Invocation Pattern
  • When a function is not the property of an object, then it is invoked as a function.
  • The this is bound to the global object
var add = function (a, b) { return a + b;};

myObject.double = function () {
    var that = this; 
    
    var helper = function () {
        that.value = add(that.value, that.value);
    };
    
    helper(); // Invoke helper as a function. 
}; // Invoke double as a method.

myObject.double( ); 
document.writeln(myObject.getValue()); // 6
The Constructor Invocation Pattern
  • The new prefix also changes the behavior of the return statement.
var Quo = function (string) {
    this.status = string;
};

Quo.prototype.get_status = function() {
    return this.status;
};

var mime = new Quo("confused");
mime.get_status();
  • Functions that are intended to be used with the new prefix are called constructors.
The Apply Invocation Pattern
  • Javascript is a functional object-oriented language, functions can have methods.
  • The apply method lets us construct an array of arguments to use to invoke a function. It also lets us choose the value of this.
var statusObject = {
    status: 'A-OK'
};

var status = Quo.prototype.get_status.apply(statusObject); // status is 'A-OK'

5. Inheritance

6. Arrays

7. Regular Expessions

8. Methods

9. Style

10. Beautiful Features