INTRODUCTION
JAVASCRIPT IS A prototype-based, object-oriented, loosely-typed dynamic scripting anguage. It has powerful features from the functional world, such as closures and higher-order functions, that are of special interest here.
JavaScript is technically an implementation of the ECMAScript language standard. It’s important to know that with Node, because of v8, you’ll be primarily dealing with an implementation that gets close to the standard, with the exception of a few extra features. This means that the JavaScript you’re going to be dealing with has some important diferences with the one that earned the language its bad reputation in the browser world.
In addition, most of the code you’ll write is in compliance with the “good parts” of JavaScript that Douglas Crockford enounced in his famous book, JavaScript: The Good Parts.
This chapter is divided into two parts:
1. Basic JavaScript. The fundamentals of the language. They apply everywhere: node, browser, and standards committee.
2. v8 JavaScript. Some features used in v8 are not available in all browsers, especially Internet Explorer, because they’ve recently been standardized. Others are nonstandard, but you still use them because they solve fundamental problems.
In addition, the next chapter covers the language extensions and features exclusively available in Node.
BASIC JAVASCRIPT
This chapter assumes that you’re somewhat familiar with JavaScript and its syntax. It goes over some fundamental concepts you must understand if you want to work with Node.js.
TYPES
You can divide JavaScript types into two groups: primitive and complex. When one of the primitive types is accessed, you work directly on its value. When a complex type is accessed,you work on a reference to the value.
1. The primitive types are number, boolean, string, null, and undefined.
2. The complex types are array, function, and object.
To illustrate:
//primitives var a = 5; var b = a; b = 6; a; // will be 5 b; // will be 6 // complex var a = ['hello', 'world']; var b = a; b[0] = 'bye'; a[0]; // will be ’bye’ b[0]; // will be ‘bye’
In the second example, b contains the same reference to the value as a does. Hence, when you access the frst member of the array, you alter the original, so a[0] === b[0].
TYPE HICCUPS
Correctly identifying the type of value a certain variable holds remains a challenge in JavaScript.
Because JavaScript has constructors for most primitives like in other languages with object-oriented features, you can create a string in these two ways:
var a = 'woot'; var b = new String('woot'); a + b; // ‘woot woot’
If you use the typeof and instanceof operators on these two variables, however, things get interesting:
typeof a; // ‘string’ typeof b; // ‘object’ a instanceof String; // false b instanceof String; // true
However, both are defnitely strings that have the same prototypical methods:
a.substr == b.substr; // true
And they evaluate in the same way with the == operator but not with ===:
a == b; // true a === b; // false
Considering these discrepancies, I encourage you to always defne your types in the literal way, avoiding new.
It’s important to remember that certain values will be evaluate to false in conditional expressions: null, undefined, ‘’, 0:
var a = 0; if (a) { // this will never execute } a == false; // true a === false; // false
Also noteworthy is the fact that typeof doesn’t recognize null as its own type:
typeof null == 'object'; // true, unfortunately
And the same goes for arrays, even if defned with [], as shown here:
typeof [] == 'object'; // true
You can be thankful that v8 provides a way of identifying an array without resorting to hacks.In browsers, you typically inspect the internal [[Class]] value of an object: Object.prototype.toString.call([]) == ‘[object Array]’. This is an immutable property of objects that has the beneft of working across diferent contexts (for example, browser frames), whereas instanceof Array is true only for arrays initialized within that particular context.
FUNCTIONS
Functions are of utmost importance in JavaScript.
They’re first class: they can be stored in variables as references, and then you can pass them around as if they were any other object:
var a = function () {} console.log(a); // passing the function as a parameter
All functions in JavaScript can be named. It’s important to distinguish between the function name and the variable name:
var a = function a () { 'function' == typeof a; // true };
THIS, FUNCTION#CALL, AND FUNCTION#APPLY
When the following function is called, the value of this is the global object. In the browser, that’s window:
function a () { window == this; // true; }; a();
By using the .call and .apply methods, you can change the reference of this to a diferent object when calling the function:
function a () { this.a == ‘b’; // true } a.call({ a: ‘b’ });
The diference between call and apply is that call takes a list of parameters to pass to the function following, whereas apply takes an array:
function a (b, c) { b == ‘first’; // true c == ‘second’; // true } a.call({ a: ‘b’ }, ‘first’, ‘second’) a.apply({ a: ‘b’ }, [‘first’, ‘second’]);FUNCTION ARITY
An interesting property of a function is its arity, which refers to the number of arguments that the function was declared with. In JavaScript, this equates to the length property of a function:
var a = function (a, b, c); a.length == 3; // true
Even though less common in the browser, this feature is important to us because it’s leveraged by some popular Node.JS frameworks to offer diferent functionality depending on the number of parameters the functions you pass around take.
CLOSURES
In JavaScript, every time a function is called, a new scope is defned.
Variables defned within a scope are accessible only to that scope and inner scopes (that is, scopes defned within that scope):
var a = 5; function woot () { a == 5; // false var a = 6; function test () { a == 6; // true } test(); }; woot();
Self-invoked functions are a mechanism by which you declare and call an anonymous function where your only goal is defning a new scope:
var a = 3; (function () { var a = 5; })(); a == 3 // true;
Tese functions are very useful when you want to declare private variables that shouldn’t be exposed to another piece of code.
CLASSES
In JavaScript, there’s no class keyword. A class is defned like a function instead:
function Animal () { }
To defne a method on all the instances of Animal that you create, you set it on the prototype:
Animal.prototype.eat = function (food) {
// eat method
}
It’s worth mentioning that within functions in the prototype, this doesn’t refer to the global object like regular functions, but to the class instance instead:
function Animal (name) { this.name = name; } Animal.prototype.getName () { return this.name; }; var animal = new Animal(‘tobi’); a.getName() == ‘tobi’; // trueINHERITANCE
JavaScript has prototypical inheritance. Traditionally, you simulate classical inheritance as follows.
You define another constructor that’s going to inherit from Animal:
function Ferret () { };
To defne the inheritance chain, you initialize an Animal object and assign it to the Ferret.prototype.
// you inherit Ferret.prototype = new Animal();
You can then define methods and properties exclusive to your subclass:
// you specialize the type property for all ferrets Ferret.prototype.type = ‘domestic’;To override methods and call the parent, you reference the prototype:
Ferret.prototype.eat = function (food) { Animal.prototype.eat.call(this, food); // ferret-specific logic here }
This technique is almost perfect. It’s the best performing across the board (compared to the alternative functional technique) and doesn’t break the instanceof operator:
var animal = new Animal(); animal instanceof Animal // true animal instanceof Ferret // false var ferret = new Ferret(); ferret instanceof Animal // true ferret instanceof Ferret // true
Its major drawback is that an object is initialized when the inheritance is declared (Ferret.prototype = new Animal), which might be undesirable. A way around this problem is to include a conditional statement in the constructor:
function Animal (a) { if (false !== a) return; // do constructor stuff } Ferret.prototype = new Animal(false)
Another workaround is to define a new, empty constructor and override its prototype:
function Animal () { // constructor stuff } function f () {}; f.prototype = Animal.prototype; Ferret.prototype = new f;
Fortunately, v8 has a cleaner solution for this, which is described later in this chapter.
TRY {} CATCH {}
try/catch allows you to capture an exception. The following code throws one:
> var a = 5; > a() TypeError: Property ‘a’ of object #<Object> is not a function
When a function throws an error, execution stops:
function () { throw new Error(‘hi’); console.log(‘hi’); // this will never execute }
If you use try/catch, you can handle the error and execution continues:
function () { var a = 5; try { a(); } catch (e) { e instanceof Error; // true } console.log(‘you got here!’); }
相关推荐
Chapter 2: The Advantages of Flight Chapter 3: Flight in the Wild Chapter 4: Building a Flight Application Chapter 5: Components Chapter 6: UI Components Chapter 7: Data Components Chapter 8: Event ...
The book then rounds off with an overview of methods to effectively use and mix functional programming with object-oriented programming. Table of Contents Chapter 1. The Powers of JavaScript's ...
#### Chapter 2: Taking the First Steps - **Understanding the Game**: An introduction to the basic mechanics and design of the game being developed. - **Swapping Jewels & Matching Three**: Detailed ...
Chapter 2: Writing a C# Program 50 The Development Environments 51 Console Applications 55 Windows Forms Applications 61 Summary 66 Chapter 3: Variables and Expressions 68 Basic C# ...
Chapter 2. The Request An In-Depth Look at XMLHttpRequest Creating the Object Asynchronous Data Transfers The Ready State HTTP Status Codes and Headers Chapter 3. The Response XML ...
**Chapter 2: Getting Started with the Eclipse Workbench** - **Setting Up the Environment**: Instructions on how to download and install Eclipse, along with recommendations for additional plugins and ...
Chapter 2. Arrays Chapter 3. Stacks Chapter 4. Queues Chapter 5. Linked Lists Chapter 6. Sets Chapter 7. Dictionaries and Hashes Chapter 8. Trees Chapter 9. Graphs Chapter 10. Sorting and Searching ...
Part 2: Ext JS components Chapter 4. Core UI components Chapter 5. Exploring layouts Chapter 6. Forms in Ext JS Chapter 7. The data store Chapter 8. The grid panel Chapter 9. Taking root with trees ...
**Chapter 2: First Steps with Ajax** - **Description**: This chapter provides a practical introduction to using Ajax in web development. It covers the basic concepts and techniques needed to start ...
Chapter 2: Designing a Microservice Architecture with Spring MVC Chapter 3: Working with Java Persistence and Entities Chapter 4: Building a REST API for a Stateless Architecture Chapter 5: ...
Includes an overview of MV* frameworks, unit testing, routing, layout management, data access, pub/sub, and client-side task automation. This book is full of easy-to-follow examples you can apply to ...
The first chapter provides an overview of JavaScript and ES2015 for those of you who haven’t yet discovered the joys of modern JavaScript. Roadmap This book is organized into three parts. Part 1 ...
Chapter 2, Understanding How Ethereum Works, explains how Ethereum works. Chapter 3, Writing Smart Contracts, shows how to write smart contracts and use geth's interactive console to deploy and ...
The first and best overview of Angular 2 on the market this guide gathers together everything there is to know about Angular 2 and groups it into intuitive sections. This book is your detailed map of ...
OAuth2 is an extremely flexi- ble authentication model, and this chapter provides a brief overview of the dif- ferent manners in which OAuth2 can be used to protect an application and its ...