Delegates vs. Function Pointers, part 5: Javascript

This is part 5 in a series about state and function pointers; part 1 is here.

Last time, we saw how C# 2 supports closures by compiling anonymous functions into member functions of a special class that holds local state from the outer function. 

Unlike the languages we’ve looked at before, Javascript has had closures baked in to the languages since its inception.  My standard example can be achieved very simply in Javascript:

var x = 2;
var numbers = [ 1, 2, 3, 4 ];
var hugeNumbers = numbers.filter(function(n) { return n > x; });

This code uses the Array.filter method, new to Javascript 1.6, to create a new array with those elements from the first array that pass a callback.  The function expression passed to filter captures the x variable for use inside the callback.

This looks extremely similar to the C# 2.0 version from last time.  However. under the covers, it’s rather different.

Like .Net managed instance methods, all Javascript functions take a hidden this parameter.  However, unlike .Net, Javascript does not have delegates.  There is no (intrinsic) way to bind an object to the this parameter the way a .Net closed delegate does.  Instead, the this parameter comes from the callsite, depending on how the function was called.  Therefore, we cannot pass state in the this parameter the way we did in C#.

Instead, all Javascript function expressions capture the variable environment of the scope that they are declared in as a hidden property of the function.  Therefore, a function can reference local variables from its declaring scope.  Unlike C#, which binds functions to their parent scopes using a field in a separate delegate object that points to the function, Javascript functions have their parent scopes baked in to the functions themselves. 

Javascript doesn’t have separate delegate objects that can hold a function and a this parameter.  Instead, the value of the this parameter is determined at the call-site, depending on how the function was called.  This is a common source of confusion to inexperienced Javascript developers.

To simulate closed delegates, we can make a method that takes a function as well as a target object to call it on, and returns a new function which calls the original function with this equal to the target parameter.  That sounds overwhelmingly complicated, but it’s actually not that hard:

function createDelegate(func, target) {
    return function() { 
        return func.apply(target, arguments);
    };
}

var myObject = { name: "Target!"};
function myMethod() {
    return this.name;
}

var delegate = createDelegate(myMethod, myObject);
alert(delegate());

This createDelegate method returns a function expression that captures the func and target parameters, and calls func in the context of target.  Instead of storing the target in a property of a Delegate object (like .Net does), this code stores it in the inner function expression’s closure.

Javascript 1.8.5 provides the Function.bind method, which is equivalent to this createDelegate method, with additional capabilities as well.  In Chrome, Firefox 4, and IE9, you can write

var myObject = { name: "Target!"};
function myMethod() {
    return this.name;
}

var delegate = myMethod.bind(myObject);
alert(delegate());
For more information, see the MDN documentation.

13 comments:

"There is no (intrinsic) way to bind an object to the this parameter the way a .Net closed delegate does."

"Javascript 1.8.5 provides the Function.bind method"

Why don't these two statements conflict ?

I meant that Javascript doesn't have intrinsic delegate objects.

Function.bind just creates a function that behaves like a delegate.
For example, there is no equivalent of the public Delegate.Target property.

Your site has a lot of useful information for myself. I visit regularly. Hope to have more quality items.
flip diving

The above article is nice and interesting, thank you willing to share! Greetings success of admin Percetakan Murah Rawamangun Jakarta Timur wish you deign to visit my website, thank you :)

Do you want to learn how to tell if your phone is tapped by police? It's important to know if you want to achieve academic success

The good article give you good informative content to the peoples like you write on wasket price in Pakistan that people want to know about the best rates.

This comment has been removed by the author.

Great! This looks very informative I will share it with my friend who is pursuing his studies in computer science, and he is learning JavaScript nowadays. This will surely help him like the way best nursing assignment writers he recommended me helped in my academics. Now it’s my time to help him as much as I can.

This comment has been removed by the author.

Thanks for sharing this blog keep sharing this.
Email Support Phone Number

This is very informative for us an also different from others.
Great! This looks very informative I will share it with my friend.
If you are troubling with email account login issue then you should contact us on Yahoo Mail Customer Care Number UK +44 800 048 5421 or visit our website.

Writing an essay is one of the most difficult tasks students face. It is required to express one’s own opinion on a particular issue so that the scientific nature of the work is preserved. In fact, the author of the essay has to balance on a fine line between the artistic and scientific style of presentation. Therefore, you should turn to professionals essay writers who can help you.

امیر حسین افتخاری گره مو

دانلود آهنگ جدید امیر حسین افتخاری گره مو
دانلود آهنگ جدید

.

ترانه: امیر حسین افتخاری . تنظیم موزیک: امیر حسین افتخاری

Post a Comment