Strano idioma JavaScript – cosa fa “/xyz/.test(function(){xyz;})” fare?

John Resig ha scritto una funzione di class elegante, sciccoso. Sto cercando di capire cosa sta succedendo e ho praticamente capito tutto tranne una sola riga:

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

Un paio di cose mi vengono subito in mente, prima xyz non è mai inizializzata come variabile; allora perché funziona? Secondo, perché sta testando /xyz/ contro qualcosa che non restituisce nulla (nessuna dichiarazione di ritorno). A meno che non ci siano alcune proprietà di javascript di cui sono inconsapevole (il che è ansible, mi piace piuttosto bene con JS e posso interpretare la maggior parte del codice che ho trovato non significa, tuttavia, che sono sullo stesso Mt . Montagna di dimensioni mai raggiunte che John Resig chiama a casa).

Per chi è curioso, ecco il codice completo inedito dal sito di john resigs John Resig Simple Javascript Ereditarietà :

 (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; }; })(); 

È solo un modo veloce e sporco per verificare se la “decompilazione della funzione” funziona.

Il metodo RegExp.prototype.test prenderà l’argomento e lo convertirà in String, il riferimento xyz all’interno della funzione non verrà mai valutato.

Perché dovresti controllare questo?

Poiché il metodo Function.prototype.toString restituisce una rappresentazione dipendente dall’implementazione di una funzione e, in alcune implementazioni, le versioni Safari precedenti, Mobile Opera e alcuni browser Blackberry, in realtà non restituiscono nulla di utile.