Vainolo's Blog

Archive for the ‘Programming’ Category

JavaScript Tutorial – Part 4: Object Creation and Prototype Chains

leave a comment

Previous Tutorial: Variable Scope and Closures

The term “Object-Oriented programming (OOP)” has been greatly overused, and JavaScript is not one of the exceptions. For someone who comes from many years programming in Java, learning JavaScript made me realize that the correct name for the paradigm used by programming languages like Java, C++, and C# (to name a few) is not Object-Oriented but Class-Oriented programming. Because in these languages what you are really defining are classes of objects and instantiating them. In contrast, JavaScript is a real Object-Oriented language since you are always handling objects. Sadly time made its thing and there is no way to change the name of the paradigms… so the paradigm used by JavaScript (and other less known languages) is called Prototype-based programming.

So why am I saying all this? Because this is a very important concept that helps understand how the language works.

In tutorial 2, we saw two ways to create objects: inline or with the new keyword before a function name. The third way to do this is using the Object.create(). Unlike the two previous ways of creating object, this one really “feels” like we are copying the existing object when creating another object.

Let’s revisit them and investigate some more. First, objects defined inline:

// Inline object creation
var a = {
    field: "a"
}
console.info("a's constructor: "+a.constructor); // prints "function Object()..."
console.info("a instanceof Object?: " + (a instanceof Object)); // prints "true"

We are inspecting a by checking it’s constructor, and using the instanceof operator which checks the prototype chain of the object (more on this later). We can see that the constructor of a is the function Object() and that as expected, it is an instance of Object.

Objects defined using the new give us a consistent way to create objects, which are also identified as being of the same instance by the instanceof operator:

// Using a constructor function
function A() {
    this.field = "a";
}
// Inline object creation
var a = new A();
console.info("a's constructor: " + a.constructor) // prints "function A()..."
console.info("a instanceof Object?: " + (a instanceof Object)); // prints "true"
console.info("a instanceof A?: " + (a instanceof A)); // prints "true"

We have now objects of a specific “class”. This is not really a class but something called [[prototype]], which in an internal property of all JavaScript objects which can be accessed using the Object.getPrototypeOf() function. But how do we create prototype chains like we do in OO languages? This can be done in a number of ways. First, by cloning objects using the Object.create method:

// Object cloning using Object.create()
var a = {
    f1: 1
}
var b = Object.create(a);
b.f2 = 2;
var c = Object.create(b);
c.f3 = 3;
console.info(c.f1 + ", "+c.f2+", "+ c.f3); // prints "1, 2, 3"

And while this creates something like inheritance, it behaves really strange when using the instanceof operator:

console.info(b instanceof a); // prints an error because instanceof expect a function as its second argument

This is the place where JavaScript comes out as a very confusing and inconsistent language. The instanceof operator actually checks if the [[prototype]] chain of the first argument contains the prototype property of the second argument (a function). But since we didn’t use a function to create these objects, we can’t use the instanceof operator. Weird…
For this case we can use the Object.getPrototypeOf() function to check the prototype chain, like this:

console.info(Object.getPrototypeOf(c) === b); // prints "true"

But IMHO this is a broken experience. So then, how can we create inheritance in JavaScript while keeping the instanceof operator working? We do this by overriding the prototype property of the constructor function:

function A() {
    f1: 1
};
// no need to override prototype here since it is our base class
var a = new A();
console.info("a instanceof A?: " + (a instanceof A)); // true

function B() {
    this.f2 = 2;
};
B.prototype = new A();
var b = new B();
console.info("b instanceof B?: " + (b instanceof B)); // true
console.info("b instanceof A?: " + (b instanceof A)); // true

function C() {
    this.f3 = 3;
}
C.prototype = new A();
var c = new C();
console.info("c instanceof C?: " + (c instanceof C)); // true
console.info("c instanceof A?: " + (c instanceof A)); // true
console.info("c instanceof B?: " + (c instanceof B)); // false

This works as expected, and while it is not the clearest syntax in the world, it is understandable. And while this works, and it took me a while to get this syntax right, I found that this is not the correct way to do it, as explained by the MDN. Some reasons for this are :

  • Using new to initialize the prototype of the constructor is problematic when the constructor requires parameters, since there are none available when the prototype is set
  • We should replace the prototype.constructor of the constructor (which sets it for all objects created by it) so that if someone, for some strange reason, wants to create an object by referring the constructor from the prototype, he will get the correct constructor

So based on these guidelines, this is how we should create new objects and prototype chains (which is similar to class hierarchies, but not exactly the same):

var A = function() { };
var B = function() { };
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
var b = new B();
console.info("b instanceof B?: " + (b instanceof B)); // true
console.info("b instanceof A?: " + (b instanceof A)); // true
console.info("Object.getPrototypeOf(b) === B.prototype?: "+ (Object.getPrototypeOf(b) === B.prototype)); // true

And as you can see, both the instanceof operator and the Object.getPrototypeOf() function behave as expected.

Now that we have this settled, let’s do some properties and functions to our objects and see what happens:

var A = function (v1) {
    this.v1 = v1;
};
A.prototype.p1 = "a";
A.prototype.f1 = function () {
    console.info("In A.f1, p1="+this.p1);
}

var B = function () {
    A.call(this, 2);
};
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
B.prototype.p1 = "b";
B.prototype.f2 = function () {
    console.info("In B.f2, p1=" + this.p1);
}

var C = function () {
    B.call(this);
}
C.prototype = Object.create(B.prototype);
C.prototype.constructor = C;
C.prototype.f1 = function () {
    console.info("In C.f1, p1=" + this.p1);
}

var a = new A(1);
console.info("v1="+a.v1);
a.f1(); // prints "In A.f1, p1=a"
var b = new B(); 
b.f1(); // prints "In A.f1, p1=b"
b.f2(); // prints "In B.f2, p1=b"
console.info("v1="+b.v1);
var c = new C();
c.f1(); // prints "In C.f1, p1=b"
c.f2(); // prints "In B.f2, p1=b"
console.info("v1="+c.v1);

We first create the prototype A by defining its constructor (the A function) and adding two properties to its prototype and assign them values (remember, functions in JavaScript are also values). Then we define prototype B which is based on the prototype of A. Of interest here is that we are replacing p1 with a new value, “masking” the value that was defined in A, and we call the parent constructor using the call function, which passes the this context. This is the way parent constructors are called… ugly, but that is how it is done. We then define C based on the prototype of B, and this time change the value of f1. The result of all this can be seen in the output that is printed to the console.

What happens internally is that when a value is referenced in an object, the interpreter first checks if it exists in the object. If not, it goes to the prototype, and then to the prototype of the prototype, until it either finds the value or gets an null prototype.

Continuing after we left of in the previous example, let’s now do something that can’t be done in regular compiled OO languages like C++/C#/Java. We’ll redefine f1 of prototype A, which changes its value for all objects that have A as its prototype (a and b):

A.prototype.f1 = function () {
    console.info("New A.f1, p1=" + this.p1);
}
a.f1(); // prints "New A.f1, p1=a"
b.f1(); // prints "New A.f1, p1=b"
c.f1(); // prints "C.f1, p1=b"

I guess that is enough for the moment. It took me a while to get all of this material inside, but now I think I understand what is happening here. Until next time, happy coding!

Next Tutorial: Statements

Written by vainolo

April 27th, 2015 at 8:02 pm

JavaScript Tutorial – Part 3: Variable Scope and Closures

leave a comment

Previous Tutorial: Variables, Functions, and Objects

Naming is one of the hardest problems in programming. Since there are many things to decide when creating a program, programmers tend to use the same name for variables in many places. And because JavaScript is a very “promiscuous” language, this can cause serious bugs that can be very hard to debug. Therefore it is very important to know what is the scope of the variables we define in our program:

Global Scope

These are variables that you declare outside functions or objects with or without the var keyword, or variables declared inside functions without the var keyword. Let’s look at an example:

a = 1;
b = 2
var c = 3;
console.info("a=" + a + ", b=" + b + ", c=" + c); // prints "a=1, b=2, c=3"
function foo() {
    a = 6;
    var b = 7
    var c = 5;
    d = 8;
    console.info("a=" + a + ", b=" + b + ", c=" + c+", d="+d); // prints "a=6, b=7, c=5, d=8"
}
foo();
console.info("a=" + a + ", b=" + b + ", c=" + c + ", d=" + d); // prints "a=6, b=2, c=3, d=8"

We can see that setting the value of the global variable a inside function foo sets the value also outside the function. This can be prevented by using the var keyword, as done with variable b. Variable c behaves as expected as it is declared both globally and locally (a.k.a masking), therefore changes to the variable are only local. Lastly, variable d is defined inside function foo without the var declaration, therefore becomes a new global variable after the function is invoked.

Function Scope

Variables declared (with the var keyword) inside a function (or an object constructor which is also a function) are scoped to the function and all functions defined inside this function (JavaScript allows us to define functions inside functions, as we will see below). But there are some gotchas that need some investigating. Let’s have an example:

var a = 1;
var b = 2;
var c;
console.info("a=" + a + ", b=" + b+", c="+c); // prints "a=1, b=2, c=undefined"
function foo() {
    var a = 3;
    var c = 4;
    console.info("a=" + a + ", b=" + b + ", c=" + c); // prints "a=3, b=undefined, c=4"
    function bar() {
        var a = 5;
        c = 6;
        console.info("a=" + a + ", b=" + b + ", c=" + c); // prints "a=5, b=7, c=6"
    }
    var b = 7;
    bar();
    console.info("a=" + a + ", b=" + b + ", c=" + c); // prints "a=3, b=7, c=6"
}
foo();
console.info("a=" + a + ", b=" + b + ", c=" + c); // prints "a=1, b=2, c=undefined"

We first define 3 global variables to use in our example. Note that c has been defined but not yet given a value, so the output of our first print statement show it as “undefined” (yea, very confusing that a defined variable is called “undefined” instead of “uninitialized”… Someone is laughing at us here).

Now comes the interesting stuff. When foo is invoked, variables a and c are redefined, masking the global variables, but when we print their value, we also get b=undefined. Wat?. What is happening here is that a few lines below we defined b giving it the value 7. When a function is called, the JavaScript interpreter scans for all variable definitions inside the function and creates for them a variable that is undefined, and then executes the function. Weird, and definitely something to remember.

Moving forward, function bar is defined and executed, with a masking the local a from foo, and the assignment of 6 to c which changes the variable from the closing scope (foo). At the end of the example, we cab see that all variables in the global scope are unchanged, because we masked them inside the functions.

Closures

A closure is a way to tie a function with variables outside of its scope. The closure of a function contains all of the variables that are not defined inside the function and used by it (and are not global). Since JavaScript allows for the definition of variables inside functions, it is very easy to show how this works:

function foo(x) {
    var a = x;
    return function () {
        a = a + 5;
        return a;
    }
}
var bar1 = foo(10);
console.info("a=" + bar1()); // prints "a=15"
var = foo(100);
console.info("a=" + bar2()); // prints "a=105"
console.info("a=" + bar1()); // prints "a=20"
console.info("a=" + bar2()); // prints "a=110"

We defined function foo which returns a function (cool, right?). This internal function uses the value of a defined in the enclosing scope, creating a closure. When we invoke bar, the value of a is already defined an matches the value of the parameter passed to foo. Furthermore, you can see from the output that each time foo is called, a new closure is created with a new value of a.

Awesome.

Next Tutorial: Object Creation and Prototype Chains

Written by vainolo

April 19th, 2015 at 8:54 pm

Posted in Programming

Tagged with , , ,

JavaScript Tutorial – Part 2: Variables, Functions, and Objects

leave a comment

Previous Tutorial: Hello JavaScript!

Variables

Javascript is a dynamically typed language, so variables don’t have types (opposite to strongly typed languages such as Ada, Java, or Scala). In general, you can declare a variable anywhere in the program by assigning it a value, but its a very good practice (and helps reduce bugs) to declare variables using the var keyword. You can declare many variables in the same line using a comma (“,”) that separates between them. You can also first declare a variable and then use it in a different place. When a variable is declared but not initialized it receives the value “undefined”.

var foo = 5;
var bar = "hello";
var foobar1 = 'hello', foobar2 = 'world', foobar3; // foobar3 is undefined

As you can see above, comments are added with “//” which comments until the end of the line. You can also add multi-line comments using “/*” to start the comment and “*/” to end the comment.

Functions

Without any types to declare, functions declarations in JS are very compact, including only the name of the function and of the parameters (which are actually optional):

function add(a,b) {
    return a+b;
}

function sayAlert(text) {
    alert(text);
}

The language is very lenient and has no compiler to check that you don’t do stupid stuff (and we all do stupid stuff now and then), so you can call a function that requires one argument with no argument or with two arguments, and this will fail at runtime (maybe):

function addOne(a) {
    return a+1;
}

var b = addOne(1,5); // will return 2, and silently ignore the value 5 passed as parameter
Var c = addOne(); // will return NaN (not a number) because "undefined"+1 is not a number

Functions in JS are treated just like values, so they can be assigned to a variable and executed using the variable’s name:

var add = function (a, b) {
    return a + b;
};

var x = add(1, 2); // x = 3
var anotherAdd = add; // same function, with a different name
var y = anotherAdd(5, 6); // y =11

Treating functions as first class entities gives a lot of power and also reduces lots of boilerplate code that needs to be added in OO languages where everything is an object (like “Comparator” objects in Java).

Objects

Objects in JavaScript are entities that map property names to values, like structs in C. And since we can use functions as values, this allows for the unification of both data and behavior in one place. Objects can be defined inline when declaring a variable, or by defining a function that initializes the properties of the object, a.k.a constructors:

var obj1 = { real: 5, imag: 5 }; // inline object definition

function Complex(real, imag) { // constructor object definition
    this.real = real;
    this.imag = imag;

    this.add = function (otherComplex) {
        this.real = this.real + otherComplex.real;
        this.imag = this.imag + otherComplex.imag;
    };

    this.sub = function (otherComplex) {
        this.real = this.real - otherComplex.real;
        this.imag = this.imag - otherComplex.imag;
    };
};

var c = new Complex(1, 2); // use the "new" operator to create the object
c.add(new Complex(1, 2));
console.info("Real " + c.real + ", imag " + c.imag); // writes "Real 2, imag 4" to the console

c.add(obj1);
console.info("Real " + c.real + ", image " + c.imag); // writes "Real 7, imag 9" to the console

In the example above we first create obj1 in-place, with two properties. After this we define the function Complex which is an object constructor that receives two arguments and initializes the value of the object. Note that the name of the function is in uppercase (convention for object constructors). We also define two object methods that modify the values of the object. To create an instance of Complex we use the new keyword. One interesting thing to note here is that while obj1 is not actually an instance of Complex it can be passed to a function that expects a Complex and things will work just fine, because obj1 contains all of the information required by the function. This gives great power, but with great power comes great responsibility, because (and I’ll say it one more time), there is no typing system or complier checking that you don’t do stupid stuff.

Functions (take two)

Now that we know about objects, we can go back and see that functions are simply objects that are interpreted in a special way. When we define a function, we are actually creating an instance of the Function object behind the scenes, and the interpreter knows how to handle the function calls. So the following three statements create the same function (there may be some differences internally, but superficially they are the same):

function mult(a, b) {
    return a * b;
};

var mult = function (a, b) {
    return a * b;
};

var mult = new Function("a", "b", "return a*b;");

Summary

We covered a lot of material in the tutorial, and this was really fun! I learned lots of new things, and this is just the beginning of a long journey.

Next Tutorial: Variable Scope and Closures

Written by vainolo

April 11th, 2015 at 11:28 pm

%d bloggers like this: