» tagged pages
» logout

(Feed found, click Add Page to syndicate.) Error finding feed, please try again » Find feed title

A Blog Page allows you to add entries, for news or other time sensitive postings

(Login required to save to your tagged pages.)
(or Cancel)

Make further edits, (or Cancel)

(Login required to save to your tagged pages.)
(or Cancel)

(Editing anonymously: to be credited for your changes, login or register a new account)

Change Page Permissions? Changing these permissions will adjust who can modify this page.

Anonymous (change)
(change)
(or Cancel)
Upload an image from your computer:
or Copy an image from a URL:
or Erase the current icon:
Icon Preview:

or Cancel

Erase apply? The contents of apply page and all pages directly attached to apply will be erased.

or Cancel

(Editing anonymously: to be credited for your changes, login or register a new account)

other page actions:
apply

apply

Tags Applied to apply

No one has tagged this page.

apply Wiki Pages

What is apply? Edit this page and describe it here.

sorted by: recent | see : popular
Content Tagged apply

toofishes.net - Git workflow with pacman

Creating and applying patches for git.

git: del.icio.us tag/git

Understanding Scope and Binding in JavaScript

At the heart of binding, it’s merely a means to control execution scope—Function x executions in the scope of object y. It can be tough to grasp at first, but with the right amount of ninja references, anything can be explained so someone can understand it.

What’s my name fool

To get a basic understanding of binding, check out this example.


var Car = function() { this.name = 'car'; }
var Truck = function() { this.name = 'truck'; }

var func = function() { alert(this.name); }

var c = new Car();
var t = new Truck();

func.apply(c);
func.apply(t);

You can pop this in Firebug and you should get two alerts with car and truck respectively. To understand why this works, you need to understand a few basic things. Functions are objects in JavaScript, and apply allows you to apply the method of one object in another object, which basically means your controlling the execution scope.

You might say that func belongs to no object, but you’d be wrong, it belongs to the window object. You could envision that all functions that aren’t scoped within a visible object (meaning one written in front of your face) can be viewed as something like this:


// Don't ever write code like this, it's just an example to help you see things clearly
function window() {
  this.func = function() { alert(this.name); }
}

Hopefully this graphic will hammer the point home.

Execution scope

For the Ruby Folk

While I’ve never had to write anything like this in Ruby, it could be done in much the same fashion.


class Car
 attr_accessor :name
 def initialize
   @name = 'car'
  end
end

class Truck
  attr_accessor :name
  def initialize
    @name = 'truck'
  end
end

def func
  puts @name
end

c = Car.new
t = Truck.new

eval "func", c.send(:binding)

Prototype and those damn blocks

A common cause of confusion amongst developers using Prototype is binding, specifically in blocks and events— the two primary places where binding is used within Prototype and JavaScript written using Prototype. Take a look at the example below.


 var Ninja = Class.create();
 Ninja.prototype = {
   initialize: function(abilities) {
     this.abilities = [
      'Kick you in the face',
      'Rip out your spleen'
     ];

     this.abilities.each(function(ability) {
       this.executeAbility(ability)
     });
   },

   executeAbility: function(ability) {
     console.log(ability);
   }
 }

// Notice this function has the same name as a method on our Ninja class.
 function executeAbility(ability) {
   console.log("I was called from the window object:" + ability);
 }

 new Ninja();

Give this interesting piece of JavaScript a run in Firebug. This should print two lines to the console that were printed from the window object. The reason this happens is because this inside the anonymous function passed to each is the window object, not our class. This is obviously not what we want, so lets use bind so we can control the execution scope. Add bind to your code like the example below and run it again.


this.abilities.each(function(ability) {
  this.executeAbility(ability)
}.bind(this));

When you execute the code above, the executeAbility from within our class should be executed. This is because we bound the execution of executeAbility to our Ninja class. Because you can never have enough visual aids, below is an overview of this in color. Prototype binding

Binding and Events

In PAJ™ (Plain Ass JavaScript) , this inside a callback is actually the element which invoked the event, so it’s fairly easy to do the code like below.


  var ninja = document.getElementById('ninja');
  ninja.addEventListener('click', function () {
    alert(this.tagName);
  }, false);

However, in Prototype this points to the window (Update: In > 1.6 this is now the element) object inside a callback so we need to use bind in order to bind it to the object the method belongs to.


var Ninja = Class.create();
Ninja.prototype = {
  ...

  addObservers: function() {
   $('item').observe('click', this.kickSomeone.bindAsEventListener(this));
  },

  kickSomeone: function(event) {
    // Works because `this` is the Ninja instance
    // Without binding it would be the window
    this.someOtherMove(); 
  }

 ...

}

The only real difference between bind and bindAsEventListener is that bindAsEventListener ensures the event object is passed as the first argument.

Bonus Mojo: Early Binding

Sometimes you need to pass an additional argument to a callback function, and you need the value of the argument at the time it was bound. To understand what I’m talking about, check out this example:


  var phrase = "This is SPAARRTTAAAA!";

  $('somelink').observe('click', sayIt);

  function sayIt(event) {
    console.log(phrase);
  }

  phrase = "Red sauce on PAASTAAAA!"

When somelink is clicked, you might think the value of phrase would be ”This is SPAARRTTAAAA!”, but this isn’t true. Even though the value of phrase is ”This is SPAARRTTAAAA!” at the time the event listener is registered, it’s value is changed before the event fires. So, what you actually get printed to the console is ”Red sauce on PAASTAAAA!”. Not quiet the dramatic effect we wanted. To correct this, we can pass the value of phrase to the callback at the time the binding was created.


  var phrase = "This is SPAARRTTAAAA!";

  $('somelink').observe('click', sayIt.bindAsEventListener(this, phrase));

  function sayIt(event, phrase) {
    console.log(phrase);
  }

  phrase = "Red sauce on PAASTAAAA!";

Now, even though the value of phrase has changed later on in our code, we’ll actually get ”This is SPAARRTTAAAA!” because we bound the value at runtime instead of execution time.

Wrapping up

As you can see, binding isn’t really that confusing, it’s just hard to explain in a way people can understand it. Hopefully I achieved that, but if I didn’t I’ll chalk it up to not enough ninja references. For some further reading check out:

Typo: Encytemedia

日下部のチラシの裏 - δ簡約

>Lispだとネイティブなサブルーチンまでの簡約のこと>評価されると実行されるは嘘。評価と実行は別

Haskell: del.icio.us tag/haskell

Username:
Password:
(or Cancel)