Introduction
* JavaScript uses class-less, prototype-oriented, or instance-based programming.
* JavaScript is case sensitive.
Variables
* Examples:
// Declare variable var v1; var V2 = 1; var v3, v4 = 'Hello', V5;
Variable Scope
* JavaScript variables are defined in function scope, Not block scope:
– variable defined within a function (called a local variable) is not visible outside the function.
– variable defined in code blocks such as if or for blocks, it is visible outside the block.
* variables defined outside any function are called global variables (limit global variables to avoid naming collisions).
* variables declared without var is automatically assigned a global scope (avoid this!).
* Variable hoisting:
var v1 = 123; function f() { alert(v1); // Undefined since v1 points to local v1. var v1 = 1; alert(v1); };
is hoisted to:
var v1 = 123; function f() { var v1; // All local variables are hoisted to top of the function alert(v1); v1 = 1; alert(v1); };
Primitive Data Types
– Use typeof to find out about variable type
* Number
// Number var n1 = 1; var n2 = 1.23; var n3 = 0123; // octal var n4 = 0xff; // hex var n5 = ce+3; // exponent var n6 = Infinity; var n7 = NaN;
* String
var s1 = 'Hello world!';
* Boolean
var b1 = true, b2 = false; // Following all evaluate to false: false "" null undefiend 0 NaN
* Undefined
* Null
Logical Operators
* Not: !
* And: &&
* Or: ||
Comparisons
* Loose equal: ==
* Strict equal: ===
* Not equal: !=
* Strict not equal: !==
* Others:
> >= < <=
Arrays
* Zero index based.
* Elements can mix and match, e.g. numbers and strings.
// Declare var a1 = []; var a2 = [1,2,3]; var a3 = ['array of arrays', a1,a2]; // Assign element a[0] = 1; a[1] = 'hi'; // Delete element delete a2[3];
Conditions and Loops
* if
// if var level = 9; var s1; if (level > 5) { s1 = 'hi'; }else if (level >9){ s2 = 'hi yo'; }else{ s3 = 'I'm not worthy!'; }
* switch
var v1 = '1', s1 = ''; switch (v1) { case 1: s1 = 'One'; break; case 2: s1 = 'Two'; break; default: s1 = 'Not sure'; break; }
* Loops
// while var i = 0; while (i < 10) { i++; } // do while i = 0; do { i++; }while(i < 10); // for for (var k = 0; k < 10; k++){ // do something } // for in var a1 = ['a', 'b', 'c']; for (var l in a1){ // do something }
Functions
* JavaScript functions always return values.
– Function returns undefined if it does not explicitly returning a value.
* Functions can be defined as either named functions or anonymous functions:
// Named function function f1(){ alert('Named function. The name is f1'); } var v1 = f1(); // invoked f1 // Anonymous function var v2 = function (){ alert('Anonymous function'); } v2(); // invoked anonymous function. Note the ()
* Functions are invoked with ()
* Function arguments are kept in special built-in variable named: arguments
// Implicitly defined special value: arguments function f2() { var r = 0; for (var i = 0; i < arguments.length; i++) { r += arguments[i]; } return r; } var sum1 = f2(1,2); // sum1 = 3 alert(sum1); var sum2 = f2(1,2,3); // sum2 = 6 alert(sum2);
* JavaScript functions are considered data which:
– contain code
– can be invoked
– can be passed as parameters
– can be returned from other functions
* Function can be assigned to a variable
// Anonymous function assigned to a variable var v1 = function (){ alert('hi'); }
* Anonymous function can be:
– passed as a parameter to another function (as callback function).
// Function that take function as parameters function sum1(a, b) { return a() + b(); } // Pass anonymous function as parameters var p1 = function(){ return 1; }; var r1 = sum1(p1, // anonymous function as parameter on the fly function(){ return 2; } ); alert(r1); // r1 = 3
* Anonymous functions are executed right away (as immediate function)
(function(name){ alert('Hello ' + name); })('world!');
Private Functions
* Functions defined within a function are private to the parent function
function outerf(name) { function innerf(){ alert('Hello ' + name + ' from inner function!'); }; alert ('Hello ' + name + ' from outer function!'); innerf(); } outerf('world');
* Private functions can be used to mimic Java getter/setter methods:
function c1(p) { var self = this; self.getVal; self.setVal; (function () { var name = p; self.getVal = function () { return name; }; self.setVal = function (v) { name = v; }; }()); }; var v1 = new c1('hello'); alert(v1.getVal()); v1.setVal('world'); alert(v1.getVal());
Predefined Functions
* parseInt(): string to int
var s1 = '123'; var n1 = parseInt(s1) // n1 = 123 var n2 = parseInt('FF', 16); // n2 = 255 var n3 = parseInt('0377', 8); // n3 = 255 var n4 = parseInt('0x377'); // n4 = 887
* parseFloat(): string to float
var s2 = '1.23'; var n2 = parseFloat(s2) // n2 = 1.23
* isNaN()
* isFinite()
* encodeURI(): encode full URI
* decodeURI()
* encodeURIcomponent(): encode partial URI
* decodeURIComponent()
var url1 = 'http://my.com/hello world'; var e1 = encodeURIComponent(url1); // e1 = 'http://my.com/hello%20world'
* eval(): do not use
* alert()
Objects
* JavaScript object contains:
– properties (name value pairs)
– methods
* Use this keyword to access properties within object
* JavaScript objects are passed by reference.
– also equal by reference like Java
Define JavaScript Objects
Use Object Literal
* Define a simple object just like Java map or C# dictionary
// Define an object var Book1 = { title: '', // property author: { // nested object firstname: '', lastname: '' }, description: '', sayhi: function(name) { // method return 'Hello ' + name + ' from ' + this.author.firstname; } }; // Set property values Book1.title = 'Book One'; Book1.author.firstname = 'John'; Book1.author.lastname = 'Doe'; Book1.description = 'This is book one.'; // Access object Book1.title; // Dot notation, title has to be an explicit string. It cannot be a variable Book1['title']; // Property notation. Property name can be a variable Book1.author.firstname; // Again, both author and firstname have to be explicit strings Book1['author']['firstname']; Book1.sayhi('world');
Use Constructor Function to Define Object
* Constructor function name is capitalized by convention.
* Use new keyword to instantiate constructor object.
* Special property named constructor holds the reference to constructor function used to construct the object.
* Once constructed, this object points to the newly construct object.
– best practice: use var self = this; to remember constructed object.
– See this article for more details on this object
function Author(firstname, lastname) { var self = this; self.firstname = firstname; self.lastname = lastname; self.fullname = function () { return self.firstname + ' ' + self.lastname; }; }; function Book(author,title){ var self = this; self.title = title; self.author = author; self.sayhi = function () { return 'Hello from ' + self.author.fullname(); }; }; var author1 = new Author('john', 'doe'); author1.constructor; // Show constructor function author1 instanceof Author; // Test instance of. Returns true var book1 = new Book(author1, 'Book One'); book1.sayhi(); // Hello from john doe // Pass by reference author1.firstname = 'jane'; book1.sayhi(); // Hello from jane doe
* More examples:
function JustName(name) { var self = this; // Remember this object self.name = name; }; JustName.prototype.title = "Mr."; JustName.prototype.hi = function() { var self = this; return "Hello " + this.title + " " + this.name; // Note use 'this' instead of 'self' object here! } var name1 = new JustName('Name1'); name1.hi(); // Hello Mr. Name1 var name2 = new JustName('Name2'); name2.hi(); // Hello Mr. Name2 // Switch this object to name2 with call or apply functions // Reads name1.hi function called by name2 object name1.hi.call(name2); // Hello Mr. Name2 name1.hi.apply(name2); // Hello Mr. Name2 // Switch this object to name2 with bind function: name1.hi.bind(name2)(); // Hello Mr. Name2
Access Object Properties
* In JavaScript, all property keys are strings!
With Square Brackets
* Evaluates the first complete expression with square brackets in a statement
* Runs toString() on it to convert it into a string
* And then uses that value for the next bracket expression
* Untill it runs out of bracket expressions.
With Dot Notation
* Can only be used to access explicit key name of a property
* Can NOT used non-string value, such as variables or numbers, in the dot notation
Built-in Objects
* Data wrapper objects:
– Object
– Array
– Function
– Boolean
– Number
– String
* Utility objects
– Math
– Date
– RegEXP
* Error objects
– Error
Object
* Methods:
var o = new Object(); o.constructor; o.toString() o.valueOf()
Array
* Array properties and methods:
var a = [1, 2, 'three']; alert(a); // 1,2,three alert(a.length); // 3 a.push('four'); alert(a); // 1,2,three,four a.sort(); alert(a); // 1,2,four,three a.join(', '); // returns comma delimited string alert(a); // 1,2,four,three var b = a.slice(1, 3); alert(a); // 1,2,four,three alert(b); // 2,four a.splice(1, 3); alert(a); // 1
Function
* Properties:
function F(name) { return 'hi ' + name; } var f1 = new F(); F.constructor; // constructor property F.length; // Length of input parameters, i.e. 1
* Prototype property
– every function has a prototype property which contains an object
– prototype chain is live (meaning changes to prototype affects all constructors)
– properties and methods can be added to function via prototype
– properties and methods are searched up the prototype chain
– reset constructor when you overwrite the prototype as in inheritance
function F1() { var self = this; self.name = 'John'; self.say = function () { return 'I\'m ' + self.name; }; }; // Add property and methods to F1 function via prototype F1.prototype.title = 'Mr.'; F1.prototype.properHi = function () { return 'Hi ' + this.title + ' I\'m ' + this.name; }; var f3 = new F1(); alert(f3.properHi()); // Hi Mr. I'm John // Reset constructor F1.prototype.constructor = F1; // Used in inheritance
* Methods:
– call: used to “borrow” a method from another function, e.g.:
var f1 = { name: 'john', say: function (who) { return 'hi ' + who + ' i\'m ' + this.name; } }; alert(f1.say('world')); // hi world i'm john var f2 = { name: 'jane' }; // Borrow f1's say method, i.e. f1.say method is called by f2 with parameter of 'Mars': alert(f1.say.call(f2, 'Mars')); // hi Mars i'm jane
– apply: similar to call except all parameters are passed in an array
Inheritance
* JavaScript uses function prototype to implement inheritance.
Example
// A helper function to extend parent constructor function extend(Child, Parent) { // Use a dummy function to break prototype chain // so changes from child won't affect parent's var F = function () { }; F.prototype = Parent.prototype; Child.prototype = new F(); // Reset constructor Child.prototype.constructor = Child; // Remember parent (super) prototype // so child can access parent functions Child.uber = Parent.prototype; }; // Define Shape parent function function Shape() { }; // Use prototype to define a common name property Shape.prototype.name = 'Shape'; // Use prototype to define a common toString property Shape.prototype.toString = function () { return this.constructor.uber ? this.constructor.uber.toString() + ', ' + this.name : this.name; }; // Define TwoDShape child function function TwoDShape() { }; // which extends from Shape parent function extend(TwoDShape, Shape); // Override name property TwoDShape.prototype.name = 'Two D Shape'; // Define Triangle child function // It has its own properties function Triangle(side, height) { this.side = side; this.height = height; }; // Triangle function extends from TwoDShape extend(Triangle, TwoDShape); // Override the name property Triangle.prototype.name = "Triangle"; // It can implement its own method Triangle.prototype.getArea = function () { return (this.side * this.height) / 2; }; // Usage var tri1 = new Triangle(10, 10); alert('triangle name: ' + tri1.name); // Triangle alert('triangle area: ' + tri1.getArea()); // 50
JavaScript Namespaces
Overview
* JavaScript namespace is just a POJO (plain old JavaScript object) used as a container/qualifier for all:
– variables
– methods
– functions
* No different to other JavaScript functions
* Used to avoid name conflicts
* By convention, namespaces are all caps?
Create Namespace
* Root namespace:
var MYAPP = MYAPP || {};
* Equivalent to:
if (typeof MYAPP == "undefined") { var MYAPP = MYAPP {}; }
Both:
– check whether namespace is already defined
– if yes, use the existing global object
– if no, create an empty global object
Sub-namespace
var MYAPP = MYAPP || {}, MYAPP.event = MYAPP.event || {}, MYAPP.event.mouse = MYAPP.event.mouse || {};
* Or
var MYAPP = MYAPP || {}; MYAPP = { MODEL: { product: function(price) { this.price = price; this.getPrice = function () { return this.price; }; } }, LOGIC: { calculateVat: function(base) { return base * 1.21; }, calculate: function() { var p = new MYAPP.MODEL.product(100); alert9this.calculateVat(p.getPrice()); } } }
Usage
* Think of namespaces as name qualifiers
* In the following example, we define a namespace named MYAPP and qualify all related variables, functions, classes, etc. with it.
var MYAPP = MYAPP || {}; MYAPP.Person = function(name) { this.name = name; if (this.name != null) { console.log("Person object named: " + this.name + " has been instantiated."); this.aliasName = name; } else { console.log("Person object has been instantiated."); this.aliasName = "unknown"; } }; MYAPP.Person.prototype.sayHello = function() { console.log("Hello " + this.aliasName); }; var p1 = new MYAPP.Person("John"); console.log("p1 aliasName: " + p1.aliasName); p1.sayHello();
JavaScript Modules
Simple Module
// Only expose MyModule in global scope var MyModule = (function (){ var _firstName = "John"; var _lastName = "Doe"; /* Private function */ function fullName() { return _firstName + " " + _lastName; } function sayHi(name) { var tmpName = name || "Stranger"; alert("Hi " + tmpName + " from " + fullName()); } /* Public function */ return { sayHi: sayHi }; })(); // Use My Module: MyModule.sayHi("Jane");
Hide/Publish Module
// Hide MyModule from global scope (function(win, doc){ var MyModule = (function (){ var _firstName = "John", _lastName = "Doe"; /* Private function */ function fullName() { return _firstName + " " + _lastName; } function sayHi(name) { var tmpName = name || "Stranger"; alert("Hi " + tmpName + " from " + fullName()); } /* Public function */ return { sayHi: sayHi }; // Expose MyModule as public module win.MyModule if (!win.MyModule) win.MyModule = MyModule; })(window, document); })(); // Use My Module: window.MyModule.sayHi("Jane");
References
* Introduction to Object-Oriented JavaScript
* JavaScript Namespaces and Modules
* Standard built-in JavaScript objects