Javascript Basic

First, let’s compare Javascript with a OOP programming language C#.

C#

Javascript

Strongly-Typed

Loosely-typed

Static

Dynamic

Classical Inheritance

Prototypal

Classes

Functions

Constructors

Functions

Methods

Functions

Strongly typed or weakly typed (loosely typed)

In general, a strongly typed language is more likely to generate an error or refuse to compile if the argument passed to a function does not closely match the expected type. On the other hand, a weakly typed language may produce unpredictable results or may perform implicit type conversion.

var x = 0;
var isNumber = typeof x == "number";
x = new Object();

Duck typing

Type is less important, but shape is important

function Feed(ani) { ani.Feed() } // accepts any object implements Feed function

Dynamic Typing

A language is statically typed if the type of a variable is known at compile time. A language is dynamically typed if the type is associated with run-time values, and not named variables/fields/etc.

var x = {
    name: "Shawn",
    city: "Atlanta"
};
x.phone = "xxx-xx-xxx";
x.makeCall = function() {
    callSomeone(this.phone);
};

Type

Type Coalescing

Javascript wants to coalesce values.

"test " + "me"
"test " + 1
"test " + true
"test " + (1 == 1)
100 + "25" // 10025

Most operators in Javascript are identical to .net, except…

  • Equality/NotEqual (==, !=): The means determines equality with coalescing (if necessary)

  • Javascript’s identically Equality operators (===, !==) which is similar to .Equal(). Determines quality without coalescing

"hello" == "hello"; // true
1 == 1; // true
1 == "1"; // true
1 === "1"; // false
1 !== "1"; // true

Types Primitives

Javascript has basic types

  • Value types: boolean, string, number

  • Reference Type: object

  • Delegate type: function

  • Special: undefined, null

var a = typeof 1; //number
var b = typeof 1.0; // number
var c = typeof true; // boolean
var d = typeof false; // boolean
var e = typeof "hello world"; // string

Number

Examples of number:

  • 1, 1.5, 070, 0xffff, 1.34e6, 10.0

  • Number.MIN_VALUE

  • Number.MAX_VALUE

  • Number.POSITIVE_INFINITY;

  • Number.NEGATIVE_INFINITY;

Operator

var fail = 10/"zero"; // NaN
var test1 = NaN == NaN; // false
var test2 = isNaN(NaN); // true
var test3 = isNaN(fail); //true
var test4 = isNaN(10); // false
var test5 = isNaN("10"); //false
var test6 = isNaN("fail");//true

All the following values are false

if("")
if(0)
if(10/0)
if(null)
if(undefined)

Function

Overloading function

Javascript does not support function overload.

function foo(one) {
    alert('first);
}
function foo(one, two) {
    alert('second');
}
foo(1); // second

The second one simply overrule the first one

Arguments object

Arguments object is available inside function body only.

function foo(one, two, three) {
    alert(arguments.length);
}
foo(1);     //1
foo(1, 2);  //2
foo(1,2,3); //3

Accessing the values through arguments object.

function foo() {
    for(var x = 0; x < arguments.length; x++) {
            alert(arguments[x]);
    }
}
foo(1, 2, 3); // 1,2,3

All functions return a value

If not defined then it’s ‘undefined’

function foo() {
    return;
}
var x = foo();

Function is just an object

Has properties and member functions

function log(s) { alert('yup'); }
var x = log.length; // 1 parameter
var y = log.name; // 'log'
var z = log.toString() // 'function log(s) { alert('yup'); }

Function Body Variable

“this” applies to the owner of the function

var f = function() {
    alert(this);
};
f(); // [Object Window]

var obj = {
    name: 'myObj',
    myFunc: function() {
            console.log(this.name);
    }
};
obj.myFunc(); // 'myObj'

var f = obj.myFunc.bind(this);
f(); // this == global object

bind() lets you change the owner.

For details, see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

Closures

JavaScript closure makes it possible for a function to have “private” variables.

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

// the counter is now 3

The variable add is assigned the return value of a self-invoking function.

The self-invoking function only runs once. It sets the counter to zero (0), and returns a function expression.

This way add becomes a function. The “wonderful” part is that it can access the counter in the parent scope.

The counter is protected by the scope of the anonymous function, and can only be changed using the add function.

The magic is that in JavaScript a function reference also has a secret reference to the closure it was created in — similar to how delegates are a method pointer plus a secret reference to an object.

function say667() {
    var num = 42;
    var say = function() { console.log(num); }
    num++;
    return say;
}
var sayNumber = say667();
sayNumber(); //logs 43
var gLogNumber, gIncreaseNumber, gSetNumber;
function setupSomeGlobals() {
    var num = 42;
    gLogNumber = function() { console.log(num); }
    gIncreaseNumber = function() { num++; }
    gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
gIncreaseNumber();
gLogNumber(); //43
gSetNumber(5);
gLogNumber(); // 5

var oldLog = gLogNumber;

setupSomeGlobals();
gLogNumber(); // 42
oldLog() //5

Note that in the above example, if you call setupSomeGlobals() again, then a new closure (stack-frame!) is created.

The old gLogNumber, gIncreaseNumber, gSetNumber variables are overwritten with new functions that have the new closure.

Closure can also introduce tricky bugs if not used correctly.

function buildList(list) {
    var result = [];
    for (var i = 0; i < list.length; i++) {
            var item = 'item' + i;
            result.push(function() { console.log(item + ' ' + list[i]) });
    }
    return result;
}
function testList() {
    var fnlist = buildList([1,2,3]);
    for (var j = 0; j < fnlist.length; j++) {
            fnlist[j]();
    }
}
testList() // logs 'item2 undefined' 3 times

This is because just like previous examples, there is only one closure for the local variables for buildList. When the anonymous functions are called on the line fnlist[j](); they all use the same single closure, and they use the current value for i and item within that one closure (where i has a value of 3 because the loop had completed, and item has a value of ‘item2’). Note we are indexing from 0 hence item has a value of item2. And the i++ will increment i to the value 3.

Self-executing function

(function() {
    var private_variable = 'private';
})();

Scope

Javascript has scope chain. When looking for the definition of a variable, the javascript engine first looks at the local execution context object. If the definition isn’t there, it jumps up the scope chain to the execution context it was created in and looks for the variable definition in that execution context object, and so on until it finds the definition or reaches the global scope.

Global scope. Objects at root are ‘global’.

var a = 'Hello'
if(true) {
    var b = a;
}
var c = b; //this works
var a = 'hello';
function() {
    var b = a;
}
var c = b; //this doesn't work

Javascript lacks real namespaces. We can mimic by creating with objects to avoid polluting the global scope.

// Construct or Import Namespace
var WilderMinds = WilderMinds || {};
WilderMinds.currentTime = function() {
    return new Date();
};

Anonymous self-executing functions: protects the global namespace by function scope All Together: Namespaces and Anonymous Self-Executing Functions

(function(ns) {
    var currentDate = new Date();
    ns.currentTime = function() {
            return currentDate;
    };
})(window.WilderMinds = window.WilderMinds || {});

OOP in Javascript

Javascript also support OOP paradiam.

Inheritance

var proto = {
    sentence: 4,
    probation: 2
};

var Prisoner = function (name, id) {
    this.name = name;
    this.id = id;
};

Prisoner.prototype = proto;
var firstPrisoner = new Prisoner('Joe', '12A');
var secondPrisoner = new Prisoner('Sam', '2BC');

Object.Create can also do the same thing

Javascript also has prototype chain. __proto__

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new().

‘Class’ in Javascript

Closures can make properties private

funciton Customer(name, company) {
    //public
    this.name = name;
    this.company = company;

    // private
    var mailServer = 'mail.google.com';

    this.sendEmail = function(email) {
            sendMailViaServer(mailServer);
    };
}

Static Members

function Customer(name, company) {
    this.name = name;
    this.company = company;
}
Customer.mailServer = 'mail.google.com';

Sharing a function

That way each instance doesn’t have it’s own copy

Customer.prototype.send = funciton(email) { … }

Basic inheritance with the Prototype object

function Cow(color) {
    this.color = color;
}
Cow.prototype = new Animal('Hay');

var c = new Cow('White');
c.feed();
var test = c instanceof Animal; // true
var test2 = c instanceof Cow; // true

Can Fake Abstract Classes with some caveats

var Animal = {
    foodType: 'None',
    feed: function() {
            log('fed the animal: ' + this.foodType);
    }
};
var a = new Animal(); //Fails (not a constructor)

Object Reflection

Property Syntaxes

  • Dot syntax: cust.name

  • Bracket Syntax: cust[“name”]

Enumerating members: simplest version of reflection

var cust = {
    name: 'Shawn',
    'company name': 'Wilder Minds',
    sendMail: function() { … }
};
for (var prop in cust) {
    alert(prop);
    alert(cust[prop]);
}

var has = cust.hasOwnProperty('name');
var isEnum = cust.propertyIsEnumerable('name');

Extension methods

prototype can be used to add extension methods Add to existing type’s prototype

Array.prototype.calculateCount = function() {
    return this.length;
};
var a = ['one', 'two'];
var count = a.calculateCount();

Written by Binwei@Trondheim

Comments

comments powered by Disqus