Javascript

  • The most popular programming language in the world.

  • The language for the web, for HTML, for servers, PCs, laptops, tablets, cell phones, and more.

  • Very widely used, and growing, very common to use JavaScript to manipulate the HTML DOM.

Primitive Datatypes

  • Number 
    • 64-bit floating point, similar to Java double and Double 
    • No integer type 
    • Special values NaN  (not a number) and Infinity

  • String 
    • Sequence of zero or more Unicode characters 
    • No separate character type (just strings of length 1)
    • Literal strings using ' or " characters  (must match)

  • Special values 
    • null  and undefined
    • typeof(null) = object;     typeof(undefined)=undefined

  • Boolean 
    • Two values: true and false
    • Empty strings, undefined, null and 0 are all treated as false

Variables

  • No type specified, can be changed dynamically
  • Variables with no value have undefined value
  • Always use var, otherwise the variable is defined on the global scope
  • It's a good practice to define variables at the beginning of a function
var pi = 3.14;                 // pi is a Numbervar person = "John Doe";       // person is a string
var answer = 'Yes I am!'; // answer is a stringconsole.log(typeof answer); // stringanswer = 10; // answer is now a numberconsole.log(typeof answer); // number
var a; // a is undefined
globalVariable = 'i am a global variable';// one statement, many variables
var lastname = "Doe", age = 30, job = "carpenter";
var lastname; console.log(lastname); // still contains "Doe"

Object == DICTIONARY

  • Every object in JS is basically a dictionary

  • Entries can be of any of the main types (object, array, function) or any of the basic types (String, Number, Date, RegExp)

  • Entries can be added dynamically at any time

  • A function defines an object with method called "()"
function max(x, y) { if (x > y) return x; else return y; };
max.description = 'return the maximum';

console.log(max.description);   // 'return the maximum'
console.log(max(1, 2));         // 2

Defining an object

  • Everything is an object- string, array, number, function
  • Properties are values associated with objects
  • Methods are actions that objects can perform
  • objects are data (variables), with properties and methods
  • Objects can be modified with new properties any time 


var person = new Object();
person.firstname = "Ami";
person.lastname = "Turgman";
person.age = 37;
person.eyescolor = 'brown';var anotherPerson = {
    firstname: 'John',
    lastname: 'Doe'
};
anotherPerson.age = 50;               // dot notation
anotherPerson['eyescolor'] = 'blue';  // key notation
console.log(person, anotherPerson);


A function member

var anotherPerson = {    firstname: 'John',
    lastname: 'Doe',
    getFullName: function () { return this.firstname + ' ' + 
                                      this.lastname; }
};
console.log(anotherPerson.getFullName());    // John Doe

  • this represents the current object the method is running on.
  • In most cases, this  points to the object which has the function as a property
  • this is resolved dynamically when the method is executed
  • this can be changed explicitely using the call/apply object functions
console.log(anotherPerson.getFullName.call(person));
    • The object person does not have the getFullName method
    • We can invoke any function on any object

Array == List

  • Arrays are just dynamic lists. They serve as a powerful container. Basic functionality of list, queue and stack.

  • Prefer using the [ ] notation to the new Array() directive.

var a = [], b = new Array();  // both equivalent
a[0] = 0, a[1] = 1, a[3] = 3; console.log(a.join(',')); // 0,1,,3 b.push(1, 'a', null, undefined, true); console.log(b); // [1, "a", null, undefined, true]

  • Array API: push, pop, shift, unshift, splice and slice


Functions

  • Always returns a value
    • undefined is used if returned value was not provided
  • Basic types passed by value, objects by reference
  • Can have any number of parameters
    • Caller can call the function with any number of arguments
    • Missing arguments will have the value undefined
    • Extra arguments will be ignored

function myFunc(a, b) {
    console.log(a, b);
}

var result = myFunc(1, 2);  // 1 2
console.log(result);        // undefined
myFunc('a');                // a undefined
    • myFunc is a named function and can be invoked by calling it

Functions returning function

  • Functions can be returned from other functions and be stored in variables
function getAdder(sum) {
    sum = sum || 0;
    return function (num) {
        sum += num;
        return sum;
    }
}

var adderFunc = getAdder(100);
console.log(adderFunc(1));     // 101
console.log(adderFunc(2));     // 103
console.log(adderFunc(3));     // 106
  • The internal adder function is an anonymous function
    • anonymous functions are usually used as callbacks
setTimeout(function(){ console.log('time expired'); }, 100);
  • Even though the adder function is being called from outside of the getAdder() function, it still has access to the sum variable. 
    • this is called closure


Closures

  • Inner functions have access to variables in the outer function.
  • Accessing variables outside of your immediate lexical scope creates a closure.
  • A closure is the local variables for a function- kept alive after the function has returned, or a closure is a stack-frame which is not deallocated when the function returns 
function sayHello(name) {    var text = 'hello ' + name;
    return function () { console.log(text); }
}

var sayHelloFunc = sayHello('ami');
sayHelloFunc(); // hello ami
function say100() {
    // Local variable that ends up within closure
    var num = 100;
    var logNum = function() { console.log(num); }
    num++;
    return logNum;
}
var logNumFunc = say100();
logNumFunc(); // 101

Closures- cont

  • Be careful when passing references to objects
  • You might get unexpected behavior when the objects values are changed

function foo(x) {    var tmp = 2;
    return function (y) {
        console.log(x.val + y + tmp);
    }
}

var obj = { val: 10 };
var bar = foo(obj); // bar is now a closure referencing obj.
bar(3);             // 15
obj.val = 20;
bar(3);             // 25

Self invoking functions

  • A function can be declared and execute itself
    • (function(params) { function body } )(variables);

var u = { a: 1, b: 2 };
var v = { a: 3, b: 4 }; console.log(u, v); // {a: 1, b: 2} {a: 3, b: 4} (function (x, y) { var tempA = x.a, tempB = x.b; //local variables x.a = y.a; x.b = y.b; y.a = tempA; y.b = tempB; })(u, v); console.log(u, v); // {a: 3, b: 4} {a: 1, b: 2} // This works because objects are passed by reference

Scope

  • The environment where variable are contained
  • Scope chain - the current scope plus all parent scopes
  • A variable that was set in a function without defining it previously will be defined in the global scope
  • Outside of a function body the scope is the global scope, in the browser this usually means 'window'
var externalVar = 'external';function myFunc() {
  var myFuncVar = 'myFunc';

  function internalFunction() {
      var internalVar = 'internal';
      console.log(externalVar, myFuncVar, 
                     internalVar, globalVar);  }

  globalVar = 'global';
  internalFunction(); // external myFunc internal global
}

myFunc();
console.log(globalVar);     // global
console.log(myFuncVar);     // myFuncVar is not defined
console.log(internalVar);   // internalVar is not defined

The arguments object


  • The arguments object is an array-like object containing all the parameters that were passed to the function

    • Used usually when there is a variable number of parameters that can be passed to a function

function sumAll() {    var total = 0;
    for (var i = 0; i < arguments.length; i++)
        total += sumAll.arguments[i];
    return total;
}
console.log(sumAll(1, 2, 3, 4, 5));     // 15

Dynamically number of params

  • It is a common design to send a single object with the parameters value
  • Can be changed dynamically without changing the API

function doWebRequest(options) {    var scheme = options.scheme || 'http';
    var port = options.port || 80;
    
    var url = scheme + '://' + options.host + ':' + port
                              + options.path;
    console.log('calling', url);
}

doWebRequest({ host: 'microsoft.com', path: '/js' });
doWebRequest({ scheme: 'https', port: 441, host: 
                       'microsoft.com', path: '/js' });
// calling http://microsoft.com:80/js // calling https://microsoft.com:441/js

Function as a class

  • Using the new keyword to create an instance of a class
  • The convention is to Capitalize constructor names

function Person(name, age) {
this.name = name; this.age = age; this.getDetails = function () { return this.name + ', ' + age; }; } var p1 = new Person('ami', 37); var p2 = new Person('guy', 28); console.log(p1.getDetails()); // ami, 37 console.log(p2.getDetails()); // guy, 28


Inheritance

  • No built-in inheritance
  • Runtime Inheritance: Clone objects and add extra properties
  • Some libraries provide all kind of 'inheritance-like' functionality


Flow control

  • If... else
if (time < 10) {
    x = "Good morning";
}
else if (time < 20) {
    x = "Good day";
}
else {
    x = "Good evening";
}
  • Switch
var day = new Date().getDay();
switch (day) {
    case 6:
        x = "Today is Saturday";
        break;
    case 0:
        x = "Today is Sunday";
        break;
    default:
        x = "Looking forward to the Weekend";
}

Loops

  • for 
var numbers = [1, 2, 3], sum = 0;for (var i = 0; i < numbers.length; i++) {
    sum += numbers[i];
}
console.log(sum);     // 6
  • for.. in (iterate through object keys)
var txt = "";
var person = { fname: "John", lname: "Doe", age: 25 };

for (var x in person) {
    txt = txt + person[x];
}
console.log(txt);     // JohnDoe25
  • While
var i = 0, x = 0;
while (i < 5) { x = x + i; i++; }


Loops- break / continue


for (var i = 0; i <= 5; i++) {
    if (i == 3) continue;
    console.log(i);               // 0, 2, 2, 4, 5
}
for (var i = 0; i <= 5; i++) { if (i == 3) break; console.log(i); // 0, 1, 2 }

Exceptions

  • Errors will happen

    • When the JavaScript engine is executing JavaScript code, different errors can occur:

      • It can be syntax errors, typically coding errors or typos made by the programmer.
      • It can be misspelled or missing features in the language (maybe due to browser differences).

    • It can be errors due to wrong input, from a user, or from an Internet server.

    • And, of course, it can be many other unforeseeable things.

Try.. Catch.. Throw


  • Can throw any object as an error

function div(x, y) {
    try {
        if (!x && !y) throw 'please provide x and y';
        if (y === 0) throw 'can not divide by 0';
        console.log(x/y);
    }
    catch(err) {
        console.log('error:', err);
    }
}
div(10, 2);      // 5
div();           // error: please provide x and y
div(10, 0);      // error: can not divide by 0 

Async Functions

  • Calling an async function with a callback function that will be invoked once it has completed its work
function doWorkAndCallMeWhenDone(callback) {
    console.log('starting work');
    setTimeout(function () {
        console.log('work completed, calling callback');
        callback();
    }, 1000);
}

var onCompleteHandler = function () {
    console.log('work is completed, now i can proceed with 
                 my next task');
};

doWorkAndCallMeWhenDone(onCompleteHandler);



Async error handling

  • A common design is that a callback function will have an error object as its first parameter and then the returned values
  • If there was an error during the async function work, it will invoke the callback with the error as its first value
  • First thing the callback will do is to check if there was an error
function doWorkAndCallMeWhenDone(callback) {    console.log('starting work');
    setTimeout(function () {
        console.log('work completed with error, notifying 
                     caller');
        callback('some error occurred');
    }, 1000);
}

doWorkAndCallMeWhenDone(function (err, result) {
    if (err) return console.error('error doing work:', err);
    console.log('work is completed, now i can proceed with 
                 next task');
});

Async function 


  • checking for errors and getting the result from the async call

function doWorkAndCallMeWhenDone(callback) {    console.log('starting work');
    setTimeout(function () {
        console.log('work completed successfully, notifying 
                     caller');
        callback(null, 'some result object');
    }, 1000);
}

doWorkAndCallMeWhenDone(function (err, result) {
    if (err) return console.error('error doing work:', err);
    console.log('work is completed with result:', result);
});

Christmas tree problem

  • Look for the tree...

function async(x, cb) {
    cb(null, x + 1);
}

function executeAsyncSequence(cb) {
    async(0, function (err, res) {
        async(res, function (err, res) {
            async(res, function (err, res) {
                cb(null, res);
            });
        });
    });
}

executeAsyncSequence(function (err, res) {
    console.log('result:', res);
});

  • There are libraries that makes this look sequentially 

Checking parameters


  • Sometimes you allow you async function to be called without providing parameters or a callback
  • This is a common design

function asyncFun(param, cb) {
    if (typeof param == 'function') cb = param;
    cb = cb || function () {console.log('completed work');};
    // do some async work
    cb();
}

asyncFun('some value', function () {console.log('here!');});
asyncFun(function () { console.log('here!'); });
asyncFun();





Javascript

By Ami Turgman

Javascript

  • 1,376
Loading comments...

More from Ami Turgman