?
var myEarth =
earth({name:"earth",numberofmoons:1});
var myjupiter=jupiter({name:"jupiter",numberofmoons:66});
The three key points here:
1. There is
code reuse.
2. There is
encapsulation. The name and numberOfMoons properties are encapsulated.
3. The child
objects can add in their own specific functionality.
Now an explanation of the syntax:
1. The base
object planet accepts some data in the spec object.
2. The base
object planet creates a closures called that which is
returned. The that object has access to everything in the spec
object. But, nothing else does. This provides a layer of
encapsulation.
3. The child
objects, earth and jupiter, set up their own data
and pass it to base planet object.
4. The planet
object returns a closure which contains base functionality. The child classes
receive this closure and add further methods and variables to it.
Hoisting
No matter where var's are declared in a function, javascript will
"hoist" them meaning that they behave as if they were declared at the
top of the function.
view
source
print?
mylocation
= "dublin"; // global variable
function outputPosition()
{
console.log(mylocation); // outputs
"undefined" not "dublin"
var mylocation
= "fingal" ;
console.log(mylocation); // outputs
"fingal"
}
outputPosition();
In the function above, the var declaration in the function means
that the first log will "see" the mylocation in the function scope
and not the one declared in the global scope. After declaration, the local
mylocation var will have the value "undefined", hence why this is
outputted first. Functions that are assigned to variables can also be
hoisted. The only difference being that when functions are hoisted, their
definitions also are - not just their declarations.Immediate Function
Expressions
Immediate function expression are executed as soon as they are defined.
view
source
print?
(function() {
console.log("I
ain't waiting around");
}());
There are two aspects of the syntax to note here. Firsty,
there is a () immediately after the function definiton, this makes it execute.
Secondly, the function can only execute if it is a function expression as
opposed to a function declaration. The outer () make the function an
expression. Another way to define a an immediate function expression is:
view
source
print?
var anotherWay
= function() {
console.log("I
ain't waiting around");
}()
JSON
JavaScript Object Notation (JSON) is a notation used to represent objects. It
is very similar to the format used for Javascript Object literals except the
property names must be wrapped in quotes. The JSON format is not exclusive to
javascript; it can be used by any language (Python, Ruby etc). JSON makes it
very easy to see what's an array and what's an object. In XML this would be
much harder. An external document - such as XSD - would have to be consulted.
In this example, Mitt Romney has an array describing who might vore for him and
an object which is his son.
view
source
print?
{"name": "Mitt
Romney", "party": "republicans", "scary": "of
course",
"romneysMostLikelyVoters":
["oilguzzlers", "conservatives"], son : {name:'George
Romney}}
Loose typing
Javascript is loosely typed. This means that variables do not need to be typed.
It also means there is no complex class hierarchies and there is no casting.
view
source
print?
var number1 = 50;
var number2
= "51";
function output(varToOutput)
{
//
function does not care about what type the parameter passed is.
console.log(varToOutput);
}
output(number1); // outputs 50
output(number2); // outputs 51
Memoization
Memoization is a mechanism whereby functions can cache data from previous
executions.
view
source
print?
function myFunc(param){
if (!myFunc.cache)
{
myFunc.cache
= {}; // If the cache doesn't exist, create it.
}
if (!myFunc.cache[param])
{
//...
Imagine the code to work out result below
//
is computationally intensive.
var result = {
//...
};
myFunc.cache[param]
= result; // now result is cached.
}
return myFunc.cache[param];
}
Method
When a function is stored as a property of an object, it is referred to as a
method.
view
source
print?
var myObject {
myProperty: function () {
//...
//
the this keyword in here will refer to the myObject instance.
//
This means the "method" can read and change variables in the
//
object.
}
}
Modules
The goal of modules is to enable javascript code bases to more modular.
Functions and variables are collated into a module and then the module
can decide what functions and what variables the outside world
can see - in the same way as encapsulations works in the object orientated
paradigms. In javascript we create modules by combining characteristics of
closures and immediate function expressions.
view
source
print?
var bankAccountModule
= (function moduleScope() {
var balance =
0; //private
function doSomethingPrivate(){ // private method
//...
}
return { //exposed to public
addMoney: function(money) {
//...
},
withDrawMoney: function(money) {
//...
},
getBalance: function() {
return balance;
}
}());
In the example above, we have a bank account module:
· The
function expression moduleScope has its own scope. The private
variable balance and the private function doSomethingPrivate, exist only within
this scope and are only visible to functions within this scope.
· The
moduleScope function returns an object literal. This is a closure which has
access to the private variables and functions of moduleScope. The returned
object's properties are "public" and accesible to the outside world.
· The
returned object is automatically assigned to bankAccountModule
· The
immediate function ()) syntax is used. This means that the module is
initialised immediately.
Because the returned object (the closure) is assigned to bankAccountModule,
it means we can access the bankAccountModule as:
view
source
print?
bankAccountModule.addMoney(20);
bankAccoumtModule.withdrawMoney(15);
By convention, the filename of a module should match its
namespace. So in this example, the filename should be
bankAccountModule.js.
Namespace
Pattern
Javascript doesn't have namespaces built into the language, meaning it is easy
for variables to clash. Unless variables are defined in a function, they are
considered global. However, it is possible to use "." in variables
names. Meaning you can pretend you have name spaces.
view
source
print?
DUBLINTECH.myName
= "Alex"
DUBLINTECH.myAddress
= "Dublin
Object Literal Notation
In javascript you can define an object as collection of name value
pairs. The values can be property values or functions.
view
source
print?
var ireland = {
capital: "Dublin",
getCapital: function () {
return this.capital;
}
};
Prototype properties (inheritance)
Every object has a prototype object. It is useful when you want to add a
property to all instances of a particular object. Suppose you have a
constructor function, which representent Irish people who bought in the boom.
view
source
print?
function IrishPersonBoughtInTheBoom(){
}
var mary = new IrishPersonBoughtInTheBoom
();
var tony = new IrishPersonBoughtInTheBoom
();
var peter = new IrishPersonBoughtInTheBoom
();
...
Now, the
Irish economy goes belly up, the property bubble explodes and you want to add a
debt property to all instances of this function. To do this you would do:
view
source
print?
IrishPersonBoughtInTheBoom.prototype.debt
= "ouch";
Then...
view
source
print?
console.log(mary.debt); // outputs
"ouch"
console.log(tony.debt); // outputs
"ouch"
console.log(peter.debt); // outputs
"ouch"
Now, when
this approach is used, all instances of IrishPersonBoughtInTheBoom share the
save copy of the debt property. This means, that they all have the same value
as illustrated in this example.
Returning functions
A function always returns a value. If return is not specified for a
function, the undefined value type will be returned.
Javascript functions can also return some data or another function.
view
source
print?
var counter = function() {
//...
var count = 0;
return function () {
return count = count +
1;
}
}
var nextValue =
counter();
nextValue(); // outputs 1
nextValue(); // outputs 2
Note, in
this case the inner function which is returned "closes" over
the count variable - making it aclosure - since it encapsulates its
own count variable. This means it gets its own copy which isdifferent to
the variable return by nextValue.count.
this keyword
The this keyword in Java has different meanings, depending on
the context it is used. In summary:
· In a method context, this refers
to the object that contains the method.
· In a function context, this refers
to the global object. Unless the function is a property of another object. In
which case the this refers to that object.
· If this is used in a
constructor, the this in the constructor function refers to
the object which uses the constructor function.
· When the apply or call methods
are used the value of this refers to what was explictly
specified in the apply or call invocation.
typeof
typeof is a unary operator with one operand. It is used to determine the types
of things (a bit like getClass() in Java). The values outputted by typeof are
"number", "string", "boolean",
"undefined", "function", "object".
view
source
print?
console.log(typeof "tony"); // outputs string
console.log(typeof 6); // outputs number
console.log(false); // outputs boolean
console.log(this.doesNotExist); // outputs
undefined if the global scope has no such var
console.log(typeof function(){}); // outputs function
console.log(typeof {name:"I
am an object"}); //outputs object
console.log(typeof ["I am an
array"]) // typedef outputs object for arrays
console.log(typeof null) // typedef outputs
object for nulls
Some implementations
return "object" for typeof for regular expressions; others return
"function". But the biggest problem with typeof is that it returns
object for null. To test for null, use strict equality...
view
source
print?
if (myobject
=== null) {
...
}
Self-redefining functions
This is a good performance technique. Suppose you have a function and the first
time it is called you want it to perform some set up code that you never want
to perfom again. You can execute the set up code and then make the function
redefine itself after that so that the setup code is never re-excuted.
view
source
print?
var myFunction
= function () {
//set
up code only to this once
alert("set
up, only called once");
//
set up code now complete.
//
redefine function so that set up code is not re-executed
myFunction
= function() {
alert("no
set up code");
}
}
myFunction(); // outputs - Set
up, only called once
myFunction(); // outputs - no set
up code this time
myFunction(); // outputs - no set
up code this time
Note, any
properties added to the set up part of this function will be lost when the
function redefines itself. In addition, if this function is used with a
different name (i.e. it is assigned to a variable), the re-definition will not
happen and the set up code will re-execute.Scope
In javascript there is a global scope and a function scope available for
variables. The var keyword does not need to be used to define
variable in the global scope but it must be used to define variable in the
local function scope. When a variable is scoped to a local function shares the
name with a global variable, the local scope takes precedence - unless var was
not used to declare the local variable in which case any local references are
pointing to the global reference. There is no block scope in javascript. By
block we mean the code between {}, aka curly braces.
view
source
print?
var myFunction
= function () {
var noBlockScope
= function ( ) {
if (true) {
//
you'd think that d would only be visible to this if statement
var d = 24;
}
if (true) {
//
this if statement can see the variable defined in the other if statement
console.log(d);
}
}
noBlockScope();
Single var pattern
You can define all variables used by a function in one place. It is
ensures tidy code and is considered best practise.
view
source
print?
function scrum() {
var numberOfProps =
2,
numberOfHookers
= 1,
numberOfSecondRows
= 2,
numberOfBackRow
= 3
//
function body...
}
If a
variable is declared but not initialized with a value it will have the
value undefined.
Strict Equality
In javascript it is possible to compare two objects using ==. However, in some
cases this will perform type conversion which can yield unexpected equality
matches. To ensure there is strict comparison (i.e. no type conversions) use
the === syntax.
print?
console.log(1
== true) // outputs true
console.log(1
=== true) // outputs false
console.log(45
== "45") // outputs true
console.log(45
=== "45") // outputs false
Truthy and Falsey
When javascript expects a boolean, you may specify a value of any type. Values
that convert to true are said to be truthy and values that convert to false are
said to be falsey. Example of truthy values are objects, arrays, functions,
strings and numbers:
view
source
print?
//
This will output 'Wow, they were all true'
if ({} &&
{sillyproperty:"sillyvalue"} && [] &&
['element']
&& function() {} && "string" && 89) {
console.log("wow,
they were all true");
}
Examples
of falsey values are empty strings, undefined, null and the value
view
source
print?
//
This will out put: 'none of them were true'
if (!("" ||
undefined || null || 0)) {
console.log("none
of them were true");
}