Comments
Line comment
// this is a line comment
Block comment
/* this is a block comment */
HTML comment (not recommended)
<!-- this is a HTML comment -->
Variable Declaration and Hoisting
Variable declaration
var name_1 [ = value_1] [ ,..., name_n [= value_n]]
var variableA = 200;
(function (){
console.log( variableA );
var variableA = 100;
console.log( variableA );
console.log( variableB );
})();
run
Function Declaration and Hoisting
Function declaration
function functionName([arguments list]) { [statements] }
Function Expression
var foo = function([arguments list]) { [statements] }
(function (){
// funcA();
// funcB();
console.log( funcA );
console.log( funcB );
// function declaration
function funcA(){ console.log("funcA");};
// function expression
var funcB = function(){console.log("funcB")};
})();
run
Conditionals
if
if (expression) { statements } [ else if (expression) {statements} ]
switch
switch (expression) { case x: statements; break; [default: ...] }
? :
condition ? val1 : val2
Loops
while
while (expression) statements
do/while
do statements while (expression);
for
for (initialize ; test ; increment) statement
labled break: label: for(...) { break/continue label; }
outer: for ( var i = 0; i< 4; ++i) {
for ( var j = 0; j< 4; ++j){
console.log("["+i+","+j+"]");
if (i === 1 && j === 1) {
break outer;
}
}
}
run
For in Loops
for (key in object)
Warning:
- Unordered
- Use on simple data object only!
- Do not use on Array
var objA = {
name: "objA"
};
objA.printName = function(){ console.log(this.name); };
for (key in objA) {
console.log(key+ " : "+ objA[key]);
}
run
Return
return expression;
function returnByArg(arg) {
switch (arg){
case 0:
return 0;
case 1:
return "A";
case 2:
return;// return undefined if no expression
}
}
console.log( returnByArg(0) );
console.log( returnByArg(1) );
console.log( returnByArg(2) );
run
Exception
try/catch/finally
try{ statements }[ catch(exception){ statements } ] [ finally{ statements } ]
throw
throw expression;
try {
console.log( "before exception thrown" );
throw {
message: "exception throw!",
code: 0xff
};
console.log( "after exception thrown" );
} catch (e) {
console.log( "exception: " + e.message );
} finally{
console.log( "finally" );
}
run
Note
with
(Unavaliable in strict mode!)
Optional Semicolons (Add Semicolons always!)
K&R Code Style is mandatory
Always add braces {} to loop and condition
// Semicolon automatically added after return case a bug.
function foo(){
console.log("foo")
return
{
name : "bar"
}
// Use K&R Style to prevent above bug
}
console.log( foo().name );
// miss semicommon on the end may cause bug
var x = function(){
}
["abc","def"].forEach(function(item){
});
run
No block scope
No block scope in ECMAScript!
Braces {} used both on block definition and object literal
(function(){
for(var block1 = 0; block1<5; ++block1) {
var block2 = block1;
}
if (true) {
var block3 = 200;
} else {
var block4 = 300; // not assigned but declared
}
console.log( block1 );
console.log( block2 );
console.log( block3 );
console.log( block4 );
})();
console.log( block1 );
run
Declaration and Expression
Function Declaration
function foo( [argument list] ) { statements }
Function Expression (lambda)
( function [bar] ( [argument list] ) { statements } )
(function(){
var foo = 100;
function funcA() {
var bar = 200;
foo = 150;
return foo + bar;
}
var funcB = function funcB(){
var bar = 300;
return foo + bar;
};
var funcC = funcB;
console.log( funcA() );
console.log( funcC() );
})();
run
Optional parameters
Additional parameter set to undefined
Arguments Object for variable-length argument list
// use undefined to detect optional parameters
function foo(a, b/*optional, default is 100*/) {
if (b === undefined) { b = 100; }
return a * b;
}
console.log( foo(5, 9) );
console.log( foo(5) );
// use arguments for any-length parameters
function bar(){
for (var i=0; i
run
Function is Object
Function is object with:
Internal [[call]] method
Internal scope context object
Internal JS code content
Other members
function foo(a,b){
return 100;
}
foo.bar = 200;
console.log( foo.length ); // Length of the arguments
console.log( foo.bar );
console.log( foo.name ); // NOT IN SPECIFICATION
run
Scope Chain and Closure
No block scope
Variable locate through scope chain to the Global scope
Closure is created when the function object is created (not function variable stack)
var p1 = 1;
function foo(a1) {
var p2 = 10;
//closure is created when function created
function bar(a2){
var p3 = 100;
console.log( p1 ); // global scope
console.log( p2 ); // parent function scope
console.log( p3 ); // function scope
console.log( a1 ); // parent function scope
console.log( a2 ); // function scope
}
return bar;
}
var _bar = foo(5);
_bar(7);
// Use closure to fix it
/*
for (var i=0; i<5; ++i) {
setTimeout( function(){
console.log(i);
},200*i+500);
// setTimeout( function(i){
// return function(){
// console.log(i);
// };
// }(i),200*i+500); }
console.log("timer start");
//*/
run
Invocation
Function Invocation
Method Invocation
Indirect Invocation
functionFoo.call( object [, arg1 [,arg2 ...]] )
functionFoo.apply( object [,argument list] )
// Method invocation
var foo = {
Name: "foo", id: 42, nickName: "bar",
// method Invocation
print: function(){
console.log( "I'm " + this.Name + "#"+ this.id );
}
};
foo.print();
function printNickName(prefix){
console.log( prefix + this.nickName + "#" + this.id );
}
// indirect invocation
printNickName.call( foo, "I'm " );
printNickName.apply( foo, ["You'are "] );
// fix it
foo.postpondPrint = function(){
setTimeout( function(){
console.log( "postpond for : " + this.Name );
}, 1000 );
};
foo.postpondPrint();
// method call on other object
// var x=Object.prototype.toString.call( Math );
// console.log(x);
run
new Invocation
Function is used for class constructor and operator
new
is used for instantiation.
Warning:
- Global Object will be polluted if operator
new
is missing
- Function may return another object
var classFoo = function(name){
this.instanceMember = 100;
this.instanceName = name;
this.print = function(){
console.log("instance: " + this.instanceName);
};
// return {};
};
var bar = new classFoo("objBar"),
bar2 = new classFoo("objBar2");
bar.print();
bar2.print();
console.log(bar2.instanceMember);
/* common bug and solution
// Bug: new is not used
var bar3 = classFoo("objBar3");
// instance variable added to global object
console.log(window.instanceMember);
bar3.print();
// solution: 1. strict mode
// 2. protection gate
// if (!(this instanceof classFoo)) {return new classFoo(name);}
//*/
run
How new Works & prototype
Operator
new
create new object in several steps:
- Create an empty object
- Assign the internal variable [[prototype]] to Constructor.prototype
- Constructor function is called on the new object
- Return the new object(or the return value of function if an object is returned)
var classFoo = function(name){
this.instanceMember = 100;
this.instanceName = name;
};
classFoo.prototype = {
classMember : 200,
print : function(){
console.log("instance: " + this.instanceName);
}
};
var bar = new classFoo("objBar"),
bar2 = new classFoo("objBar2");
bar.print();
bar2.print();
console.log(bar2.classMember);
console.log(bar2.instanceMember);
/* Create a new object manualy (not avaliable on IE, the */
/* interal [[prototype]] variable is not public in IE ) */
/*
var bar3 = {};
bar3.__proto__ = classFoo.prototype;
classFoo.call(bar3, "objBar3")
bar3.print();
console.log(bar3.classMember);
console.log(bar3.instanceMember);
//*/
run
prototype chain
Prototype chain is a feature common used for class inheritance in ECMAScript
// Simple Example
function Animal(){
}
Animal.prototype = {
shout: function(){
console.log(this.name + ' shout:"' + this.voice + '"!');
}
};
function Cat(name){
// missing: call the constructor function of parent class
this.name = name;
}
Cat.prototype = new Animal();
Cat.prototype.voice="meow";
var kitty = new Cat("kitty");
var doraemon = new Cat("doraemon");
kitty.shout();
doraemon.shout();
run
Extension of Native Prototypes
Native Object can be extended by modify the prototype of their Native Constructors.
Note: Monkey patching on native object is not recommended, the only exception is backport the features of newer JavaScript specification.
// example: extend native Function. NOT RECOMMENDED!
function foo(){}
var bar = " bar ";
Function.prototype.showMe = function(){
console.log("It's function [" + this.name + "]");
};
foo.showMe();
// example: backport new method in ECMA5 to ECMA3
String.prototype.trim = function(){
return this.replace(/^\s*|\s*$/g, "");
};
console.log("[" + bar.trim() +"]");
run
More on prototype
in
vs hasOwnProperty
: prototype chain will not be checked for hasOwnPropert
instanceof
: check if the class function's prototype in the prototype chain
isPrototypeOf
(ECMA5): check for the instance
Object.getPrototypeOf
(ECMA5): get the prototype of an instance
function Animal(){
}
Animal.prototype = { shout: function(){} };
function Cat(name){ this.name = name; }
Cat.prototype = new Animal();
Cat.prototype.voice="meow";
var kitty = new Cat("kitty");
console.log("in: " + ("voice" in kitty));
console.log("hasOwnPropert: " +
kitty.hasOwnProperty("voice"));
console.log("instanceof: " +
(kitty instanceof Animal));
console.log("isPrototypeOf: " +
Animal.prototype.isPrototypeOf(kitty));
var kitty_Proto_ = Object.getPrototypeOf(kitty);
console.log("Object.getPrototypeOf: " +kitty_Proto_);
console.log("Object.getPrototypeOf is Animal:" +
(kitty_Proto_ === Animal.prototype));
console.log("Object.getPrototypeOf is Animal:" +
(kitty_Proto_ === Cat.prototype));
run
Global Object
The root object of ECMAScript environment. window
in browser and global
in nodejs.
Value properties
NaN Infinity undefined
Function properties
eval()
parseInt(string, radix) parseFloat(string) isNaN(number) isFinite(number)
decodeURI(encodedURI) encodeURI(uri) decodeURIComponent(encodedURIComponent) encodeURIComponent(uriComponent)
escape/unescape
Object Objects
Constructor methods: (ECMA5 Only)
Property related
defineProperty defineProperties getOwnPropertyDescriptor getOwnPropertyNames
Internal state
freeze isFrozen preventExtensions isExtensible seal isSealed
Others
getPrototypeOf create keys
Object Objects
Portotype methods
constructor
toString
toLocaleString
valueOf
hasOwnProperty
propertyIsEnumerable
isPrototypeOf
(ECMA5)
Array Objects
Literal (NOTE: Always use literal instead of constructor to create array)
[value1, value2, ...]
Constructor methods:
isArray
(ECMA5)
// Length is 3.
var a1 = new Array(x1, x2, x3);
// Length is 2.
var a2 = new Array(x1, x2);
// If x1 is a number and it is a natural number the length will be x1.
// If x1 is a number but not a natural number this will throw an exception.
// Otherwise the array will have one element with x1 as its value.
var a3 = new Array(x1);
// Length is 0.
var a4 = new Array();
run
Array Objects
Portotype variables and methods
Methods will generate a new Array
concat slice
Methods will modify the Array itself
pop push shift unshift splice reverse sort
(unstable, string comparison default)
Methods to convert to string
toString join
New methods in ECMA5 (implemented in es5-polyfill)
indexOf lastIndexof every some forEach map filter reduce reduceRight
Instance variables
length
Array Objects
Note:
Do not use for ( ... in ...)
loop on Array object, elements may be unordered, methods on polyfill may be enumerated.
typeof
method is not working for type check, use Object.prototype.toString.call()
instead (or Array.isArray
if ECMA5 is avaliable).
Methods are working on other Array-like object too.
// Object.prototype.toString.call()
console.log(Object.prototype.toString.call([]));
console.log(Object.prototype.toString.call(/ /));
console.log(Object.prototype.toString.call(new Date()));
// Array-like oObject
var foo = {
0: { bar: 100, name: "A" },
1: { bar: 300, name: "B" },
2: { bar: 200, name: "C" },
length : 3
};
Array.prototype.sort.call(foo, function(a,b){
return a.bar > b.bar ? 1 : a.bar < b.bar? -1 : 0;
});
console.log(JSON.stringify(foo, null, " "));
run
Primitive type wrappers
There are three primitive type wrappers in ECMAScript make primitive types working like Object.
String
Number
Boolean
Automatiocally boxing: primitive value will be boxing to object wrapper when method or variable propertie is invoced.
Note: Do not use new
to create primitive wrapper!
// same
console.log( true.toString() );
console.log(new Boolean(true).toString());
console.log( "abc".length );
console.log( 12..toFixed(3) );
// DO NOT USE new TO CREATE PRIMITIVE WRAPPER
var foo = new String("foo");
var bar = new Boolean(false);
var foobar = new Number(123);
console.log( typeof foo );
console.log( typeof bar );
console.log( typeof foobar );
if (bar) {
console.warn( "it's false!" );
}
// Used for type conversion is OK but not recommended
var x = Number("123");
// console.log( typeof x );
run
Type wrapper:String
Constructor methods:
Generate character from unicode
fromCharCode()
console.log( String.fromCharCode( 0x597d ) );
run
Type wrapper:String
Portotype methods:
Generate a new String
charAt concat replace slice(start, end) substring(start, end) toLowerCase toUpperCase trim() substr
Return other value
indexOf lastIndexOf search(regexp) match(regexp) localeCompare charCodeAt([]) split(seperator)
Instance variables:
length
Type wrapper:Number
Constructor variable properties:
MAX_VALUE
: 1.7976931348623157*10308
MIN_VALUE
: 5*10-324
NaN
NEGATIVE_INFINITY
POSITIVE_INFINITY
Type wrapper:Number
Portotype methods for string format:
toString( [ radix ] )
toFixed(fractionDigits)
toExponential (fractionDigits)
toPrecision (precision)
Type wrapper:Boolean
Nothing special.
Function Objects
Portotype methods and variable properties:
toString
apply
call
bind
(ECMA5, implemented in es5-polyfill)
Instance variables:
length
var foo={
name: "bar",
value: 100
}
function printMe(){
console.log( this.name+ " " + this.value);
}
var wrapper = printMe.bind(foo);
wrapper();
run
Date Objects
Constructors:
new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )
(Note: local time)
new Date (value)
(value can be Date String or number)
Constructor methods:
parse(string)
Parse Date String to number(milliseconds)
UTC(year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )
Return a number(milliseconds)
now()
Return the current time in number(ms)
Date Objects
Portotype methods:
String formatter
toDateString() toTimeString() toISOString() toJSON()
Value manipulate
(get/set)FullYear, Month, Date, Day, Hours, Minutes, Seconds, MilliSeconds
(getUTC/setUTC)FullYear, Month, Date, Day, Hours, Minutes, Seconds, MilliSeconds
getTime/setTime getYear/setYear
Other
getTimezoneOffset
RegExp Objects
Literal
/[RegExp pattern]/[gmi]
Constructor
new RegExp(pattern, flags)
Portotype methods:
exec() test()
Regexp instance variable properties:
global ignoreCase multiline lastIndex source
Error Objects
Portotype variable properties:
name message
Built-in Error Types:
EvalError RangeError ReferenceError SyntaxError TypeError URIError
The Math Object
Constants
E LN10 LN2 LOG2E LOG10E PI SQRT1_2 SQRT2
Functions
Trigonometric functions
sin(x) cos(x) tan(x) asin(x) acos(x) atan(x) atan2(y,x)
Arithmetic functions
pow(x,y) sqrt(x) exp(x) log(x) abs(x) floor(x) ceil(x) round(x)
Other functions
max ([ value1 [ , value2 [ , … ] ] ])
min ([ value1 [ , value2 [ , … ] ] ])
random ()
The JSON Object
JSON (JavaScript Object Notation) is a lightweight data-interchange format (http://www.json.org/).
Functions
parse(text, [receiver])
stringify ( value [ , replacer [ , space ] ] )
var foo = JSON.parse('{"foo":100,"bar":{"a":"string"}}');
console.log( foo.foo );
console.log( JSON.stringify(foo.bar, null, " ") );
run