奇怪的 JavaScript 习语 - "/xyz/.test(function(){xyz;})" 是做什么的?

IT技术 javascript regex function
2021-02-21 06:50:31

John Resig 写了一个漂亮的 Class 函数,很时髦。我试图弄清楚发生了什么,并且除了一行之外几乎所有的东西都弄清楚了:

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

有几件事立即浮现在脑海中,首先xyz是永远不会初始化为变量;那么为什么这样做呢?其次,为什么要/xyz/针对不返回任何内容的内容进行测试(无返回语句)。除非有一些我不知道的 javascript 的漂亮属性(这是可能的,我认为自己很擅长 JS 并且可以解释我遇到的大多数代码,但是,这并不意味着我在同一个山上.约翰雷西格称之为家的珠穆朗玛峰大小的山)。

对于那些好奇的人,这里是来自 john resigs 站点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个回答

这只是检查“函数反编译”是否有效的一种快速而肮脏的方法。

RegExp.prototype.test方法将接受参数并将其转换为字符串,xyz永远不会评估函数内部的引用。

你为什么要检查这个?

因为该Function.prototype.toString方法返回函数的依赖实现的表示,并且在某些实现中,例如较旧的 Safari 版本、Mobile Opera 和某些 Blackberry 浏览器,它们实际上不返回任何有用的东西。

@trinithis,好吧,typeof foo == 'function会起作用,但问题是您最终会包装每个函数对象,即使它们不使用_super. Resig 只是检查每个函数,看看它是否在其主体中使用了_super标识符。如果_super出现在函数体中,则他将该函数包装到另一个函数中,在该函数中,他首先通过分配this._super. 然后他执行了原来被检查过的,被证明可以使用的函数,_super最后他恢复了this._super……的值
2021-04-16 06:50:31
@CMS 是的,过了一会儿我终于明白了..)
2021-04-22 06:50:31
@mykhal,xyz正是您真正要寻找的,以了解函数反编译正常工作。它只是检查一个转换为字符串的函数,生成一个包含函数体的字符串......
2021-04-27 06:50:31
那么,xyz匿名函数体不是不必要的吗?
2021-04-28 06:50:31
只是添加一个注释:为了使测试通过 jslint,它必须是 /var xyz/.test(function () { var xyz; }) ?/\b_super\b/ : /[\D|\d]*/; 为什么 \D|\d 很简单,一个捕获所有数字,另一个捕获其他所有数字,它相当于 .* 但这被认为是“不安全的”,因为您没有定义限制。让我永远意识到他们所说的不安全的“.”是什么意思。投票给你,也标记为答案,非常感谢CMS。
2021-04-28 06:50:31