Strange JavaScript idiom - what does “/xyz/.test(f

2019-01-04 08:52发布

John Resig wrote a nifty Class function, swanky. I'm trying to figure out what is going on, and have pretty much everything figured out except a single line:

fnTest = /xyz/.test(function () {xyz;}) ? /\b_super\b/ : /.*/;

A couple things immediately jump to mind, first xyz is never initialized as a variable; so why then does this work? Second, why is it testing /xyz/ against something that is not returning anything (no return statement). Unless there is some nifty properties of javascript I'm unaware of (which is possible, I fancy myself rather good at JS and can interpret most the code I come across it doesn't, however, mean I'm eve on the same Mt. Everest sized mountain that John Resig calls home).

For those curious, here is the full unedited code from john resigs site John Resig Simple Javascript Inheritance:

(function () {
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };

})();

1条回答
【Aperson】
2楼-- · 2019-01-04 09:24

It is just a quick & dirty way to check if "function decompilation" works.

The RegExp.prototype.test method will take the argument and it will convert it to String, the xyz reference inside the function is never evaluated.

Why would you have to check this?

Because the Function.prototype.toString method returns an implementation-dependent representation of a function, and in some implementation, such older Safari versions, Mobile Opera, and some Blackberry browsers, they don't actually return anything useful.

查看更多
登录 后发表回答