Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript in ten minutes: What is going on in this example code illustrating lazy scoping?

I've been re-reading Spencer Tipping's excellent Javascript in Ten Minutes and for the life of me can't figure out what is going on in this example of using lazy scoping to create syntactic macros:

var f = function () {return $0 + $1};  
var g = eval (f.toString ().replace (/\$(\d+)/g,  
           function (_, digits) {return 'arguments[' + digits + ']'}));  
g(5,6); // => 11 (except on IE)

In particular,

  1. $0 and $1 are being replaced by a function definition -- how does that function get evaluated? (Presumably by eval(), but I'm not seeing this).
  2. What is the purpose of the single underscore argument in the function -- if I take it out, the code no longer works. Presumably it's just a place holder, but why is it needed?
like image 855
pgoetz Avatar asked Jun 26 '12 21:06

pgoetz


People also ask

What kind of scoping does JavaScript?

JavaScript has 3 types of scope: Block scope. Function scope. Global scope.

What is the hardest topic in JavaScript?

Asynchronous JavaScript (promises, callbacks, async/await) Closures. The event loop. Recursion.

What is JavaScript theory?

JavaScript is a multi-paradigm, dynamic language with types and operators, standard built-in objects, and methods. Its syntax is based on the Java and C languages — many structures from those languages apply to JavaScript as well.


1 Answers

I'll agree with pst here, this code is pretty scary. It's horrific for readability. It's neat, though:

  1. f is defined as sort of a placeholder function. It seems to be the actual macro itself; the numeric variables will be replaced when it's evaluated into g. They act as positional, variadic arguments which we'll see below.
  2. g is where the magic happens: the function definition of f is converted to a string, and the numeric variables in the macro definition f are replaced with references to the indexed arguments for as many numeric variables there are in the definition of f (hence the regular expression and call to replace). The underscore is just used because we don't care about the first parameter to the callback for replace.
  3. The whole thing is then evaled, once f is essentially expanded to the following:

    function () { return arguments[0] + arguments[1] }
    

So, it's neat, in that you could define f with as many positional numeric arguments as you wanted:

var f = function() { return $0 + $1 + $2 }

and it'd get evaluated to

function() { return arguments[0] + arguments[1] + arguments[2] }

Neat, but useless, arguably dangerous, impractical and hard to read. I probably wouldn't ever use it.

like image 143
Wyatt Anderson Avatar answered Sep 24 '22 06:09

Wyatt Anderson