Javascript - The Good Parts
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'