WebFund 2015W Lecture 4

From Soma-notes

Video

Video from the lecture given on January 14, 2014 is now available:

Notes

HTML, the DOM, and JSON

HTML tags have various attributes. For example, an <img> tag can have an href attribute. The DOM (Document Object Model) is an object representation of an HTML page in which the tags are objects with their attributes as their properties. The DOM also contains information about the browser environment. With HTML and the DOM tags can have unknown attributes/properties which are simply ignored if they are not recognized. There may be some differences in the way tags and their attributes are recognized in different browsers.

When trying to represent HTML objects in another language, unknown properties may be problematic. By avoiding classes and doing this dynamically, JavaScript can have a flexible representation of the DOM. JSON (JavaScript Object Notation) is a standard for the representation of data which acts as a simpler and more concise alternative to XML. The syntax for JSON is a subset of JavaScript.

JavaScript

Objects

As opposed to other languages which require the definition of classes to make objects, JavaScript allows for an instance of an object to be created without the need for a defined class. In the following example, an object is created with a single attribute. The attribute of the object is then modified.

>var car = {colour: "blue"};
>car.colour = "red";
>car.foo;
undefined

On the last line of the example, undefined is returned when accessing an attribute of the object which it does not have. Note that in JavaScript, undefined is an actual value. It is important to note that accessing an undefined attribute of an object does not cause any errors. This is different from how most languages behave. With JavaScript, it simply indicates to you that the attribute has not yet been defined however it does technically have a value (undefined).

Variable scoping

Variables declared within a function are know as local variables and these variables can only be accessed within the scope of that function or another function nested inside that scope. This can be seen in the following example.

function printName(){
   var name = "Somayaji"; // this is a local variable and it is only accessible in the printName function
   console.log(name); // prints out Somayaji
}

Variables declared outside of all functions are called global variables and can be accessed anywhere in the code. Note that variables declared without the keyword var are always global, even when declared inside a function. This is a bug in JavaScript.

When trying to access a variable at the global level which has not been defined, a reference error is thrown. JavaScript is not compiled so there are no compilation errors, only runtime errors.

>foo
ReferenceError...
Closure

The pattern of public and private members is possible in JavaScript through the use of 'closure'. By default, everything is public. Private members are managed by creating them as variables within the scope of a function, thus they can only be accessed locally. A nested function inside this function will also have access to these variables. In order to access them elsewhere, the nested function can be returned from the function in which it is nested to act as a helper function (a getter or setter of sorts).

In the following example, the value returned by the function is incremented but the private member b remains unchanged:

function containsB(){
   var b = 5;
   return b;
}
containsB() + 1;

In this example, calling the returned function will actually change the value of the private member b:

function containsB(){
   var b = 5;
   return function(){
      b = b + 1;
   }
}

var incrementB = containsB();
incrementB();
Function invocation

In JavaScript, you can call functions in 4 contexts:

  • Function context
    var foo = function(){
       alert(this);
    }
    foo();
    
  • Method context
    var foo = {};
    foo.someMethod = function(){
       alert(this);
    }
    foo.someMethod();
    
  • Constructor context
    function Foo(){
       this.someAttribute = "hi";
    }
    var myObject = new Foo();
    
  • Apply context

Note that when using the 'this' keyword in a function which belongs to an object (member context), 'this' refers to the object in which the function has been called as a method. When calling a function which is not the member of an object, 'this' refers to the global object. The global context is represented by this global object.

Prototyping and inheritance

Inheritance in JavaScript can be achieved by setting the prototype attribute of a constructor function to a parent object. Since JavaScript has no classes, it uses prototyping for inheritance. Prototyping allows for objects to access attributes which they do not have through their prototype chain. Note that the parent object can be modified after an object has been prototyped from it yet the protoyped object will still have access to the newly changed attributes of the parent. Each time an attribute of the prototyped object is accessed which it does not have, it will look through the prototype chain at that time. As the term "chain" implies, there can be a chain of multiple prototypes. Furthermore, the protoyped attributes can be specified at the level of the newly created objects. When this happens, that object will use its own version of the attributes. The lowest definition on the prototype chain will always be used when accessing attributes. Note that defining an attribute of an object does not affect things up the chain (parent objects are not affected). The following example demonstrates inheritance through prototyping:

>function Sportscar{
>   this.colour = "red";
>}
>var car = {doors: "open"};
>Sportscar.prototype = car;
>var sienna = new Sportscar();
sienna.colour; //we see the colour assigned from the constructor
>red
sienna.doors; //we see the doors value inherited through the prototype
>"open"
car.doors = "closed";
sienna.doors; //we see that the value in the sienna object has been updated because it is reference through the prototype chain
>"closed"
>car.colour = "blue";
>sienna.colour; //we see that the sienna object has kept its red colour value because it was defined in the constructor so the prototype chain is not needed
"red"