Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Sunday, August 18, 2013

'this'

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
   },
};

foo.first();
foo.second();

Everything works fine.

Now there is a need for function second to call function first. Try this and it will fail.

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
     first();
   },
};

foo.second();

One way to fix this problem is to hardcode value foo inside the second function. Following code works.

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
     foo.first();
   },
};

foo.second();

Above code works but hardcoding the value of foo inside the object literal is not good. A better way would be to replace the hardcoded name with this .

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
     this.first();
   },
};

foo.second();

All is good.

Chasing this

Javascript allows one to create function inside a function. Now I am changing the implementation of method second. Now this method would return another function.

var foo = {

   first: function(){
       console.log('I am first');
   },

   second: function(){
     return function(){
         this.first();
     }
   },
};

foo.second()();

var foo = {

   first: function(){
       console.log('I am first');
   },

   second: function(){
     return function(){
         this.first();
     }
   },
};

foo.second()();

var foo = {

   first: function(){
       console.log('I am first');
   },

   second: function(){
     var self = this;
     return function(){
         self.first();
     }
   },
};

foo.second()();

Thursday, December 13, 2012

[JS] Function Bind

Why you need this?
 var x = 9;
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81

var getX = module.getX;
getX(); // 9, because in this case, "this" refers to the global object

// create a new function with 'this' bound to module
var boundGetX = getX.bind(module);
boundGetX(); // 81

// ----------------------------------------------------


Function.prototype.bind = function(oThis) {
  var args = Array.prototype.slice.call(arguments, 1);
  var fToBind = this;
  var fToReturn = function() {
    return fToBind.apply(oThis, args.concat(Array.prototype.slice.call(arguments)))
  }
  return fToReturn;
}

[JS] Function Currying

Currying allows you to easily create custom functions by partially invoking an existing function. Here’s a simple example:

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

//create function that returns 10 + argument
var addTen = add.curry(10);
addTen(20); //30

// ----------------------------------------

Function.prototype.curry = function() {
    if (arguments.length<1) {
        return this; //nothing to curry with - return function
    }
    var fToBind = this;
    var args = Array.prototype.slice.call(arguments); // Converting to array
    return function() {
        return fToBind.apply(this, args.concat(toArray(arguments)));
    }
}

Tuesday, August 14, 2012

Closures

Classic "last value" problem, when function declared within loop ends up using last value of an incrementing variable:

for (var i = 0; i < 10; i++)
{
    document.getElementById('box' + i).onclick = function()
    {
        alert('You clicked on box #' + i);
    };
}
This assigns 10 functions as event handlers to corresponding elements.Our intention is to have different `i` values in each of the event handlers. But this is not at all what happens in reality.

If you look closer, it's easy to see what's really going on. Each of the functions assigned to `onclick` has access to `i` variable. Since `i` variable is bound to the entire enclosing scope—just like any other variable declared with `var` or as function declaration—each of the functions have access to the same `i` variable. Once this snippet is executed, `i` variable keeps its last value—the one that was set when loop ended.

So how do we fix it? By taking advantage of closures, of course. The solution is simple: scope each of the `i` values to the level of event handler. Let's see how this is done:

for (var i = 0; i < 10; i++)
{
    document.getElementById('box' + i).onclick = (function(index) {
        return function() {
            alert('You clicked on box #' + index);
        };
    })(i);
}

OR

function makeHandler(index) 
{
    return function() 
    {
        alert('You clicked on box #' + index);
    };
}
for (var i = 0; i < 10; i++) 
{
    document.getElementById('box' + i).onclick = makeHandler(i);
}