Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird regex in inherit.js (by John Resig) - why, what and how? [duplicate]

I recently used a little utility library by John Resig, called inherit.js. I usually try to understand the core parts of the libraries I am using, and after a lot of head scratching I finally understood the hard bits of the code (namely how he could call the corresponding method of the super class).

The 1% bit I do not get is related to a regex

fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
  1. The regex /xyz/ is tested against a function. Both MSDN and MDN state that test takes a string as the argument. No mention of a function, but since there are no errors in the console, I guess it must fly, but how does it work?
  2. The next WTF is that the function body is xyz;. This function cannot be executed, because it would otherwise result in a "ReferenceError: xyz is not defined". Right? So what does it do?
  3. If the result of the test is true, then fnTest is equal to a regex which checks for _super on a word boundary, else a regex that matches on anything. Double WTF; again how and why.

Later on there is a related bit of code, where this regex is being used.

  // Check if we're overwriting an existing function
  prototype[name] = typeof prop[name] == "function" &&
    typeof _super[name] == "function" && fnTest.test(prop[name])
        ? aFunctionThatCanCallSuper /* Lots of code */
        : prop[name];

The bit I am wondering about here is fnTest.test(prop[name]). I understand all the other tests, which check if the property exists, is a function, etc, but not what the regex test does. Anyone?

like image 501
oligofren Avatar asked Jun 21 '13 05:06

oligofren


1 Answers

The what:

test only takes strings as input, so a function will be toStringed, like will any other object that's not a string. xyz is not interpreted as a variable, but as a string, so it won't throw a reference error. This happens in other places as well, take this for example:

var a = function(){}; var b = function(){};
console.log(a + b); // `+` coerces with `toString`

The why:

The serialization of functions in old browsers is not reliable and might not output the _super property in the function's body, but (I'm assuming) something like function{[native code]} or [object Object]; in those cases use a regex such as /.*/ to match anything and not perform the optimizations that can be done in browsers that output the correct result.

Related links for more info:

http://blog.buymeasoda.com/understanding-john-resigs-simple-javascript-i/ (found by Andreas)
http://es5.github.io/x15.3.html#x15.3.4.2
http://bytes.com/topic/javascript/answers/747203-function-tostring

like image 197
elclanrs Avatar answered Oct 14 '22 01:10

elclanrs