Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are values of function(a, b)?

I am testing module example from JavaScrit: The Good Parts. I don't know who passes in a and b in function(a, b). Somehow it works.

Function.prototype.method = function(name, f) {
    this.prototype[name] = f;
    return this;
}
String.method('de', function() {
    var entity = {
        lt : '<',
        gt : '>'
    };
    return function() {
        return this.replace(/&([^&;]+);/g, function(a, b) {
            document.write("<br> a=" + a + " b=" + b);
            var r = entity[b];
            return typeof r === 'string' ? r : a;
        });
    };
}());
document.write("<br>" + '&lt;&gt'.de());
like image 906
J Any Avatar asked Nov 12 '22 19:11

J Any


1 Answers

To understand what is happening one has to have a very close look at what is actually done.

Function.prototype.method = function(name, f) {
    this.prototype[name] = f;
    return this;
}

This part is pretty clear, it is "shortcut" to extend the Prototype of any object.

The magic happens in the second part of your code, the previously defined function is supplied with an self-executing function as the second parameter!

String.method('de', function() {
    var entity = {
        lt : '<',
        gt : '>'
    };
    return function() {
        return this.replace(/&([^&;]+);/g, function(a, b) {
            // "this" will refer to the object the function is bound to.
            document.write("<br> a=" + a + " b=" + b);
            var r = entity[b];
            return typeof r === 'string' ? r : a;
        });
    };
}()); <-- The magic happens here!

This means, the JavaScript interpreter will use the return value of the "first inner" function (the one directly supplied to String.method) as the actual function, since the "first inner" function is executed before assigning it to the String.prototype.

The code below does the same but puts one more variable (de) in the local scope. The approach above does not pollute the scope, it is a more elegant way to achieve this. You could even unwrap it further putting entity in the local scope.

var de = function() {
    var entity = {
        lt : '<',
        gt : '>'
    };
    return function() {
        return this.replace(/&([^&;]+);/g, function(a, b) {
            // "this" will refer to the object the function is bound to.
            document.write("<br> a=" + a + " b=" + b);
            var r = entity[b];
            return typeof r === 'string' ? r : a;
        });
    };
};
String.method('de', de());

Now to your question regarding how a and b come into play! This is related on how String.replace behaves when second parameter passed is a function. The link DCoder provided in the comments explains this pretty good! The parameter a is the entire matched substring, b is the first matched "parenthesized submatch".

like image 191
clentfort Avatar answered Nov 15 '22 10:11

clentfort