Javascript – Javascript execution – The this keyword



Javascript – Javascript execution – The this keyword

0 3


javascript-introduction

An introduction to javascript for newbies

On Github redaemn / javascript-introduction

If you find this presentation useful, please let me know
made with ♡ by ReDaemn using reveal.js

Javascript

“The World's Most Misunderstood Programming Language (Has Become the World's Most Popular Programming Language)”

-- Douglas Crockford -- http://javascript.crockford.com/

Despite its popularity, few know that JavaScript is a very nice dynamic object-oriented general-purpose programming language. You can do anything with it!! (cloud9, this presentation!!)

Presentation Goal

  • Explain some peculiar concepts about JavaScript, not found in any classical OO language ...
  • ... so that you will be able to understand what this code does and why it works
    /* The .bind method from Prototype.js */
    Function.prototype.bind = function(){ 
      var fn = this,
        args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    
      return function(){ 
        return fn.apply(object, 
          args.concat(Array.prototype.slice.call(arguments))); 
      }; 
    };
At the end of this presentation, you should be able to go out there, pick the source code of a javascript framework (jQuery, Kendo, ...), read it and understand why it works (and hopefully learn many more interesting things!!)

function()

  • function declaration
    function diameter(radius) {
      return 2 * radius;
    }
  • function expression
    var diameter = function (radius) {
      return 2 * radius;
    };
- functional language, functions are first class citizens - note the semicolon (;) at the end of the expression

function.call()

  • directly using parentheses
    diameter(2);
  • using Function object methods
    diameter.call(null, 2);
    diameter.apply(null, [2]);
  • The arguments object
    function test() {
      console.log(arguments);
    }
    
    test();
    test("a");
    test("a", 5);
JavaScript performs no check on the number of arguments. Any formal parameter that does not receive an actual value will have undefined as its value.

scope

  • NO block scope
    function test() {
      /* console.log(i);
      console.log(j); */
    
      for (var i = 1; i < 5; i++) {
        var j = i+1;
      }
    
      console.log(i);
      console.log(j);
    }
    
    test();
  • just two types of scope
    • function scope
    • global scope
Indeed, a variable is defined even BEFORE its "var" definition, show a demo. We'll see why We'll see what global scope means in a moment

Javascript execution

  • Execution context
    function adder(base) {
      return function(num) {
        return base + num;
      };
    }
  • Variable Object (Activation Object)
  • Global Object
- a function's execution context delimits a function's scope and includes everything that's inside curly brackets ({}) in a function's definition (it's defined statically, based on how the code is written) - An execution context has a variable object. Any variables and functions defined inside the function are added as properties on this object - Before running any code, the JavaScript engine creates a global object whose initial properties are the built-ins defined by ECMAScript, such as Object, String, Array and others, in addition to host defined properties - all these are NOT objects usable by your program, they're used by the javascript runtime to execute the code

Javascript execution

For any formal parameters, add corresponding properties on the variable object and let their values be the values passed as arguments to the function. For any function declarations, add corresponding properties on the variable object whose values are the functions. If a function declaration uses the same identifier as one of the formal parameters, the property is overwritten. For any variable declarations, add corresponding properties on the variable object and initialize the properties to undefined, regardless of how the variables are initialized in source code. If a variable uses the same identifier as an already defined property (i.e., a parameter or function), do not overwrite it. Now you undestand the behaviour seen previously. Best practice to avoid problems: declare all variables at the start of a scope (i.e. a function)

Scope Chain

  • Whenever a function is called, control enters a new execution context.
  • The activation object is used for identifier resolution inside the function. In fact, identifier resolution occurs through the scope chain, which starts with the activation object of the current execution context. At the end of the scope chain is the global object.
function adder(base) {
  return function(num) {
    return base + num;
  };
}
var inc = adder(1);
console.log(inc(5));

Javascript objects (intro)

Container of key-value pairs

var o1 = {
  name: “circle”,
  radius: 2,
  diameter: function () { /* ... */ }
};

console.log(o1.name);

var o2 = {
  “invalid-key-constant”: “value”
};

console.log(o2[“invalid-key-constant”]);

The this keyword

  • this is set implicitly when calling a function using parentheses
  • calling it as a function causes this to be set to the global object
    var a = "a";
    
    function test() {
      return this.a;
    }
    
    test();
this is not caused by the fact that the "test" function is declared in the same scope of the "a" variable; show an example with a function defined inside "test" function

The this keyword

  • calling it as a method causes this to be the object through which the function is called
    var person = {
      name: "World",
      sayHi: function() {
        return "Hello " + this.name;
      }
    };
    
    person.sayHi();
  • allows JavaScript objects to share function objects and still have them execute on the right object
    var person2 = {
      name: "Gabriele",
      sayHi: person.sayHi
    };
    
    person2.sayHi();

The this keyword

  • Explicitly setting this
person.sayHi.call({ name: "John" });

Javascript is single-threaded

Image taken from http://ejohn.org/blog/how-javascript-timers-work/

Closure

function adder(base) {
  return function(num) {
    return base + num;
  };
}
  • inside the anonymous function returned by adder, the base variable is known as a free variable
  • it lives on after the adder function has finished executing, as long as someone holds a reference to the returned function
JavaScript supports nested functions, which allows for closures that can keep private state, and can be used to implement many useful patterns

Stateful Functions

  • A closure can maintain state through its free variables.
  • The scope chain that allows access to these free variables is only accessible from within the scope chain itself, which means that free variables by definition are private.
function uniqueIdGenerator(start) {
  var currentId = start || 0;

  return function() {
    return currentId++;
  }
}
Every new execution of "uniqueIdGenerator" creates a new execution context and a new scope chain; this means that a generator's state cannot interfere with the state of a previously created generator

Immediately Called Anonymous Functions

(function () {
  /* ... */
}());
  • avoid littering the global scope with temporary variables by simply wrapping our code in a self-executing closure
  • simulate block scope
var names = ['John', 'Gabriele'];

(function() {
  var i;
  for (i = 0; i < names.length; i++) {
    console.log("Hello " + names[i]);
  }
}());

console.log(i);
JavaScript only has global scope and function scope, we need to avoid leaking objects into the global scope because doing so increases our chances of naming collisions with other scripts (and bugs in our scripts) This pattern is used EVERYWHERE, see some jQuery plugin (i.e. cycle jquery plugin)

Namespaces

A good strategy to stay out of the global scope is to use some kind of namespacing

var reply = {
  applicationConfig: {
    config1: "...",
    config2: 42
  }
  customCalendar: function() { /* ... */ }
};
You could create your personal framework and it should have a single entry point stored inside the global object. This pattern too is used EVERYWHERE (jQuery, Kendo, ...)

Resources and Credits

(in random order)

Final quiz

Start!