【问题标题】:What's the point of exporting a new function that calls another instead of the original?导出一个调用另一个而不是原始函数的新函数有什么意义?
【发布时间】:2019-12-13 20:28:51
【问题描述】:

在探索(为了好玩,手动反编译)一些与 Webpack 捆绑并拆分为多个文件的 JavaScript 代码时,我发现一个模块做了一件奇怪的事情:它创建一个函数,然后导出一个调用它的函数的函数创建,而不是仅仅导出第一个函数。

代码的简化、去混淆和反编译版本:

/*
  __d is the function used for registering modules
  It takes in three arguments:
   - a callback, the module's factory
   - the module's ID
   - the dependency map, an array of the IDs of the module's dependencies (which
     is passed in as the last argument of the factory)
*/
__d(
  function(
    window,
    require,
    import_default,
    import_all,
    module,
    exports,
    dependency_map
  ) {
    // Both are regular functions (not arrow functions)
    function example(arg1, arg2) {
      // ...
      // (note that the function does not use `this`)
      // (although it does import another module via `require`)
      return result;
    }

    // Why not just `exports.run_example = example`?
    exports.run_example = function(arg1, arg2) {
      return example(arg1, arg2);
    }
  },
  // And the other two arguments passed into __d (removed because unimportant)
)

这是为什么?不只是导出第一个函数在功能上是等效的吗?

【问题讨论】:

    标签: javascript webpack module bundling-and-minification code-splitting


    【解决方案1】:

    这是为什么?只是导出第一个函数在功能上不一样吗?

    不完全是,但非常接近。使用您的example,它实际上并没有太大区别,因为正如您所说,它没有使用this,并且因为它使用两个正式的非休息参数而不使用arguments。所以基本上是等价的,顺便说一句。 :-)

    以下是我可以看到的差异,这可能与您的代码无关:

    1. example 不会被调用时使用与调用 run_example 相同的 this。它将始终获得默认的this(松散模式下的全局this,严格模式下的undefined)。你的example 没有使用this,所以没有相关的区别。

    2. example 总是会得到正好两个参数,不管run_example 被调用的次数有多少。由于您的 example 使用两个形式参数,并且不使用 arguments 或其余参数,因此同样没有相关区别。

    3. 在大多数现代 JavaScript 引擎上,example 的名称(它的 name 属性和堆栈跟踪中出现的内容)是 examplerun_example 的名字是 run_example(是的,真的,这是 ES2015 规范中的新内容)。因此,您会看到堆栈跟踪的差异,或者代码是否检查了导出函数的 name 属性。

    4. 显然,当通过run_example 调用时,还有一个函数调用和一个堆栈帧。您的代码可能不在乎。

    这是一个 sn-p,说明了大多数现代引擎上的 1-3 三个:

    "use strict";
    function example(arg1, arg2) {
        console.log("example:     typeof this? " + typeof this);
        console.log("example:     arguments.length? " + arguments.length);
    }
    var run_example = function(arg1, arg2) {
        console.log("run_example: typeof this? " + typeof this);
        console.log("run_example: arguments.length? " + arguments.length);
        return example(arg1, arg2);
    };
    
    // Call with `this` set to a blank object and no arguments:
    run_example.call({});
    // Outputs:
    // run_example: typeof this? object
    // run_example: arguments.length? 0
    // example:     typeof this? undefined
    // example:     arguments.length? 2
    
    // Call with the default `this` and four arguments:
    run_example(1, 2, 3, 4);
    // Outputs:
    // run_example: typeof this? undefined
    // run_example: arguments.length? 4
    // example:     typeof this? undefined
    // example:     arguments.length? 2
    
    // Function names
    console.log("example.name is " + example.name);
    console.log("run_example.name is " + run_example.name);
    .as-console-wrapper {
        max-height: 100% !important;
    }

    显示与 ES2015+ 休息参数差异的示例:

    "use strict";
    function example(...args) {
        console.log("example: args.length? " + args.length);
    }
    var run_example = function(arg1, arg2) {
        return example(arg1, arg2);
    };
    
    // Call with the default `this` and one argument:
    run_example(1);
    // Outputs:
    // example:     args.length? 2
    
    // Whereas calling it directly:
    example(1);
    // Outputs:
    // example: args.length? 1
    .as-console-wrapper {
        max-height: 100% !important;
    }

    【讨论】:

    • 尽管对此答案表示赞同(与您的其他答案一样,它是正确的),但值得一提的是,OP 说 “请注意该函数不使用 this,这使得#1 并不重要,而 JS 忽略较少/额外参数的事实对于 #2 也是如此。所以,真正的问题:有任何相关区别吗?
    • 感谢您的澄清!所以,如果函数不使用this,也不访问arguments,它们等价的,对吧?
    • @DamianoMagrini - 基本上,是的。 :-) 我已经更新了答案。
    • @GerardoFurtado -(谢谢!)假设example 也不使用rest 参数来知道传递给它的参数数量,基本上没有真正相关的差异。我已经更新了答案以更好地反映这一点(并指出我错过的一对:-))。
    猜你喜欢
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2019-01-20
    • 1970-01-01
    相关资源
    最近更新 更多