You are previewing JavaScript: The Good Parts.

JavaScript: The Good Parts

Cover of JavaScript: The Good Parts by Douglas Crockford Published by O'Reilly Media, Inc.
  1. JavaScript: The Good Parts
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Preface
      1. Conventions Used in This Book
      2. Using Code Examples
      3. Safari® Books Online
      4. How to Contact Us
      5. Acknowledgments
    4. 1. Good Parts
      1. Why JavaScript?
      2. Analyzing JavaScript
      3. A Simple Testing Ground
    5. 2. Grammar
      1. Whitespace
      2. Names
      3. Numbers
      4. Strings
      5. Statements
      6. Expressions
      7. Literals
      8. Functions
    6. 3. Objects
      1. Object Literals
      2. Retrieval
      3. Update
      4. Reference
      5. Prototype
      6. Reflection
      7. Enumeration
      8. Delete
      9. Global Abatement
    7. 4. Functions
      1. Function Objects
      2. Function Literal
      3. Invocation
      4. Arguments
      5. Return
      6. Exceptions
      7. Augmenting Types
      8. Recursion
      9. Scope
      10. Closure
      11. Callbacks
      12. Module
      13. Cascade
      14. Curry
      15. Memoization
    8. 5. Inheritance
      1. Pseudoclassical
      2. Object Specifiers
      3. Prototypal
      4. Functional
      5. Parts
    9. 6. Arrays
      1. Array Literals
      2. Length
      3. Delete
      4. Enumeration
      5. Confusion
      6. Methods
      7. Dimensions
    10. 7. Regular Expressions
      1. An Example
      2. Construction
      3. Elements
    11. 8. Methods
    12. 9. Style
    13. 10. Beautiful Features
    14. A. Awful Parts
      1. Global Variables
      2. Scope
      3. Semicolon Insertion
      4. Reserved Words
      5. Unicode
      6. typeof
      7. parseInt
      8. +
      9. Floating Point
      10. NaN
      11. Phony Arrays
      12. Falsy Values
      13. hasOwnProperty
      14. Object
    15. B. Bad Parts
      1. ==
      2. with Statement
      3. eval
      4. continue Statement
      5. switch Fall Through
      6. Block-less Statements
      7. ++ −−
      8. Bitwise Operators
      9. The function Statement Versus the function Expression
      10. Typed Wrappers
      11. new
      12. void
    16. C. JSLint
      1. Undefined Variables and Functions
      2. Members
      3. Options
      4. Semicolon
      5. Line Breaking
      6. Comma
      7. Required Blocks
      8. Forbidden Blocks
      9. Expression Statements
      10. for in Statement
      11. switch Statement
      12. var Statement
      13. with Statement
      14. =
      15. == and !=
      16. Labels
      17. Unreachable Code
      18. Confusing Pluses and Minuses
      19. ++ and −−
      20. Bitwise Operators
      21. eval Is Evil
      22. void
      23. Regular Expressions
      24. Constructors and new
      25. Not Looked For
      26. HTML
      27. JSON
      28. Report
    17. D. Syntax Diagrams
    18. E. JSON
      1. JSON Syntax
      2. Using JSON Securely
      3. A JSON Parser
    19. Index
    20. About the Author
    21. Colophon
    22. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Invocation

Invoking a function suspends the execution of the current function, passing control and parameters to the new function. In addition to the declared parameters, every function receives two additional parameters: this and arguments. The this parameter is very important in object oriented programming, and its value is determined by the invocation pattern. There are four patterns of invocation in JavaScript: the method invocation pattern, the function invocation pattern, the constructor invocation pattern, and the apply invocation pattern. The patterns differ in how the bonus parameter this is initialized.

The invocation operator is a pair of parentheses that follow any expression that produces a function value. The parentheses can contain zero or more expressions, separated by commas. Each expression produces one argument value. Each of the argument values will be assigned to the function's parameter names. There is no runtime error when the number of arguments and the number of parameters do not match. If there are too many argument values, the extra argument values will be ignored. If there are too few argument values, the undefined value will be substituted for the missing values. There is no type checking on the argument values: any type of value can be passed to any parameter.

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 object. If an invocation expression contains a refinement (that is, a . dot expression or [subscript] expression), it is invoked as a method:

// Create myObject. It has a value and an increment
// method. The increment method takes an optional
// parameter. If the argument is not a number, then 1
// is used as the default.

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

A method can use this to access the object so that it can retrieve values from the object or modify the object. The binding of this to the object happens at invocation time. This very late binding makes functions that use this highly reusable. Methods that get their object context from this are called public methods.

The Function Invocation Pattern

When a function is not the property of an object, then it is invoked as a function:

var sum = add(3, 4);    // sum is 7

When a function is invoked with this pattern, this is bound to the global object. This was a mistake in the design of the language. Had the language been designed correctly, when the inner function is invoked, this would still be bound to the this variable of the outer function. A consequence of this error is that a method cannot employ an inner function to help it do its work because the inner function does not share the method's access to the object as its this is bound to the wrong value. Fortunately, there is an easy workaround. If the method defines a variable and assigns it the value of this, the inner function will have access to this through that variable. By convention, the name of that variable is that:

// Augment myObject with a double method.

myObject.double = function (  ) {
    var that = this;    // Workaround.

    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.value);     // 6 

The Constructor Invocation Pattern

JavaScript is a prototypal inheritance language. That means that objects can inherit properties directly from other objects. The language is class-free.

This is a radical departure from the current fashion. Most languages today are classical. Prototypal inheritance is powerfully expressive, but is not widely understood. JavaScript itself is not confident in its prototypal nature, so it offers an object-making syntax that is reminiscent of the classical languages. Few classical programmers found prototypal inheritance to be acceptable, and classically inspired syntax obscures the language's true prototypal nature. It is the worst of both worlds.

If a function is invoked with the new prefix, then a new object will be created with a hidden link to the value of the function's prototype member, and this will be bound to that new object.

The new prefix also changes the behavior of the return statement. We will see more about that next.

// Create a constructor function called Quo.
// It makes an object with a status property.

var Quo = function (string) {
    this.status = string;
};

// Give all instances of Quo a public method
// called get_status.

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

// Make an instance of Quo.

var myQuo = new Quo("confused");

document.writeln(myQuo.get_status(  ));  // confused

Functions that are intended to be used with the new prefix are called constructors. By convention, they are kept in variables with a capitalized name. If a constructor is called without the new prefix, very bad things can happen without a compile-time or runtime warning, so the capitalization convention is really important.

Use of this style of constructor functions is not recommended. We will see better alternatives in the next chapter.

The Apply Invocation Pattern

Because 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. The apply method takes two parameters. The first is the value that should be bound to this. The second is an array of parameters.

// Make an array of 2 numbers and add them.

var array = [3, 4];
var sum = add.apply(null, array);    // sum is 7

// Make an object with a status member.

var statusObject = {
    status: 'A-OK'
};

// statusObject does not inherit from Quo.prototype,
// but we can invoke the get_status method on
// statusObject even though statusObject does not have
// a get_status method.

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

The best content for your career. Discover unlimited learning on demand for around $1/day.