Speaking JavaScript
Preface
Don't get bogged down by the details.
JavaScript Command Lines: Node.js
Chapter 1: Basic JavaScript
1.1 Syntax
1.1.1 Overview of Syntax
// two slashes start single-line comments
var x; // declaring a variable
x = 3 + y; // assigning a value to the variable 'x'
foo(x, y); // calling function 'foo' with parameters 'x' and 'y'
obj.bar(3); // calling method 'bar' for object 'obj'
//A conditional statement
if (x === 0) { // Is 'x' equal to zero?
x = 123;
}
//Defining function 'baz' with parameters 'a' and 'b'
function baz(a, b) {
return a + b;
}
Note the two different uses of the equal sign:
(1) A single equals sign (=) is used to assign a value to a variable.
(2) A triple equal sign (===) is used to compare two values.
1.1.2 Statements v. Expression
statement: do things
expression: value
JS has two different ways to do if-then-else
(1) statement:
var x;
if (y >= 0) {
x = y;
} else {
x = -y;
}
(2) expression
var x = y >= 0 ? y : -y;
1.1.3 Semicolons: recommended
semicolons terminate statements, but not blocks. There is one case where you will see a semicolon after a block: a function expression is an expression that ends with a block.
var f = function () { }; // function expr. inside var decl.
1.2 Values
1.2.1 Primitive Values v. Objects
JavaScript makes a somewhat arbitrary distinction between values:
(1) The primitive values are booleans, numbers, strings, null and undefined.
(2) All other values are objects.
A major difference between the two is how they are compared; each object has a unique identity and is only(strictly) equal to itself.
In contrast, all primitive values encoding the same value are considered the same.
1.2.2 Primitive Values
(1) Compared by value: the "content" is compared
e.g. 3 === 3 , 'abc' === 'abc'
(2) Always immutable: properties can't be changed
> var str = 'abc';
> str.length = 1; // try to change property 'length'
> str.length // no effect
3
1.2.3 Objects
(1) Plain Objects
{
firstName: 'Jane',
lastName: 'Doe'
}
(2) Arrays
['apple', 'banana', 'cherry']
(3) Regular Expression
/^a+b+$/
(4) Characteristics
Comapred Reference:
1)
> {} === {}
false
2)
> var obj1 = {};
> var obj2 = obj1;
> obj1 === obj2;
true
Mutable by Default:
> var obj = {};
> obj.foo = 123; // add property 'foo'
> obj.foo
123
1.2.4 undefined and null
undefined: no value
null: no object
checking for undefined and null:
if (!x) {...}
1.2.5 typeof and instanceof
(1) type of value
> typeof true
'boolean'
>typeof null
'object' // this is a bug and cannot be fixed
(2) instance of
> {} instanceof Object
true
1.3 Booleans
JavaScript has two kinds of equalty:
(1) Normal, or "lenient", (in) equalty: == and !=
(2) Strict (in)equalty: === and !==
Normal equality is considered (too) many values to be equal (p84) which hide bugs. Therefore, always using strict equality is recommended.
1.4 Numbers
All numbers in JavaScript are floating-point
Special Numbers:
(1) NaN ("Not a Number")
> Number('xyz')
NaN
(2) Infinity: Infinity is LARGER and SMALLER than any other number
> 3 / 0
Infinity
1.5 Operators
+-*/%++--
The global object Math(P31) provides more arithmatic operators
1.6 Strings
slice/trim/indexOf
1.7 Functions
function add(param1, param2) {
return param1 + param2;
}
> add(6, 1)
7
> add('a', 'b')
'ab'
Another way of defining add() is:
var add = function (param1, param2) {
return param1 + param2;
};
1.7.1 Function and var declaration are hoisted, while assignments performed by them are not.
function foo() {
bar(); // OK, bar is hoisted
function bar() {
...
}
}
function foo() {
bar(); // Not OK, bar is still undefined
var bar = function() {
...
}
}
1.7.2 You can call any function in JavaScript with an arbitrary amount of arguments; the language will never complain.
1.7.3 special variable argument
1.8 Strict Mode
1.9 Variables Are Function-Scoped, Hoisted
1.10 Closure
Each function stays connected to the variables of the functions that surround it, even after it leaves the scope in which it is created.
function createIncrementor(start) {
return function() { // (1)
start++;
return start;
}
}
The function starting in line (1) leaves the context in which it is created, but stays connected to a live version of start:
> var inc = cerateIncrement(5);
> inc()
6
> inc()
7
> inc()
8
A closure is a function plus the connection to the variables of its surrounding scopes. Thus, what createIncrementor() returns a closure.
1.11 Objects and Constructors
1.11.1 Single Objects
You could consider an object to be a set of properties, where each property is a (key, value) pair. The key is a string, and the value is any JavaScript value.
'use strict'
var jane = {
name: 'Jane',
describe: function () {
return 'Person named' + this.name;
}
}
> jane.name // get
'Jane'
> jane.name = 'John'; // set
> jane.newProperty = 'abc'; // property created automatically
The in operator checks whether a property exists:
> 'newProperty' in jane
true
> 'foo' in jane
false
The delete operator removes a property:
> delete jane.newProperty
true
1.11.2 Arbitrary Property Keys
Use square brackets to get and set the property:
> var obj = { hello: 'world' };
> var x = 'hello';
> obj[x]
'world'
> obj['hel' + 'lo']
'world'
1.11.3 Extracting Methods
If you extract a method, it loses its connection with the object. On its own, the function is not a method anymore, and this has the value undefined (in strict mode).
Extract the method describe from jane, put it into a variable func, and call it. However, that doesn't work:
> var func = jane.describe;
> func()
TypeError: Cannot read property 'name' of undefined
Solution: use the method bind(). It creates a new function whose this always has the given value.
> var func2 = jane.describe.bind(jane);
> func2()
'Person named Jane'
1.11.4 Functions inside a method (这里有点没搞懂)
Every function has its own special variable this. This is inconvenient if you nest a function inside a method, because you can't access the method's this from the function. The following is an example where we call forEach with a function to iterate over an array:
var jane = {
name: 'Jane',
friends: [ 'Tarzan', 'Cheeta' ],
logHiToFriends: function () {
'use strict';
this.friends.forEach(function (friend) {
// 'this' is undefined here
console.log(this.name + ' says hi to ' + friend);
});
}
}
> jane.logHiToFriends()
TypeError: Cannot read property 'name' of undefined
Solution 1: store this in a different variable
logHiToFriends: function () {
'use strict';
var that = this;
this.friends.forEach(function (friend) {
console.log(that.name + ' says hi to ' + friend);
});
}
Solution 2: forEach has a second parameter that allows you to provide a value for this:
logHiToFriends: function () {
'use strict';
this.firends.forEach(function (friend) {
console.log(that.name + ' says hi to ' + friend);
}, this);
}
Attention: Function expression are often used as arguments in function calls in JavaScript. Always be careful when you refer to this from one of those function expressions.
1.11.5 Constructors: Factories for Objects
// Set up instance data
function Point(x, y) {
this.x = x;
this.y = y;
}
//Method
Point.prototyoe.dist = function () {
return Math.sqrt(this.x*this.x + this.y*this.y);
}
> var p = new Point(3, 5);
> p.x
3
> p.dist()
5.83....
p is an instance of Point:
> p instanceof Point
true
1.12 Arrays
Array Methods:
slice/push/pop/shift/indexOf/join
map creates a new array by applying a function to each element of an existing array:
> [1,2,3].map(function (x) { return x*x })
[ 1, 4, 9 ]
1.13 Regular Expression(Chapter 19)
Method: test(): Is There a Match?
> /^a+b+$/.test('aaab')
true
> /^a+b+$/.test('aaa')
false