导出调用另一个函数而不是原始函数的新函数有什么意义?
What's the point of exporting a new function that calls another instead of the original?
在探索(为了好玩,手动反编译)一些与 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)
)
这是为什么?不只是导出第一个函数在功能上是等价的吗?
Why is this? Isn't just exporting the first function functionally equivalent?
不完全是,但非常接近。对于您的 example
,它确实没有太大区别,因为正如您所说,它没有使用 this
并且因为它使用了两个正式的非剩余参数而不使用 arguments
。所以 基本上 等效,抛开狡辩。 :-)
以下是我能看到的差异,这对您的代码可能无关紧要:
example
将不会使用与 run_example
相同的 this
来调用。它将始终获得默认值 this
(松散模式下的全局 this
,严格模式下的 undefined
)。您的 example
不使用 this
,因此没有相关差异。
example
总是会恰好得到两个参数,不管 run_example
被调用的次数是多少。由于您的 example
使用两个形式参数并且不使用 arguments
或其余参数,所以这里没有相关差异。
在大多数现代 JavaScript 引擎上,example
的名称(其 name
属性 以及出现在堆栈跟踪中的内容)是 example
; run_example
的名字是 run_example
(是的,真的,这是 ES2015 规范中的新内容)。所以你会看到堆栈跟踪的差异,或者如果代码检查导出函数的 name
属性。
显然,通过 run_example
调用时,多了一个函数调用,因此多了一个堆栈帧。您的代码可能不关心。
这是一个片段,说明了大多数现代引擎上的 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+ rest 参数差异的示例:
"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;
}
在探索(为了好玩,手动反编译)一些与 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)
)
这是为什么?不只是导出第一个函数在功能上是等价的吗?
Why is this? Isn't just exporting the first function functionally equivalent?
不完全是,但非常接近。对于您的 example
,它确实没有太大区别,因为正如您所说,它没有使用 this
并且因为它使用了两个正式的非剩余参数而不使用 arguments
。所以 基本上 等效,抛开狡辩。 :-)
以下是我能看到的差异,这对您的代码可能无关紧要:
example
将不会使用与run_example
相同的this
来调用。它将始终获得默认值this
(松散模式下的全局this
,严格模式下的undefined
)。您的example
不使用this
,因此没有相关差异。example
总是会恰好得到两个参数,不管run_example
被调用的次数是多少。由于您的example
使用两个形式参数并且不使用arguments
或其余参数,所以这里没有相关差异。在大多数现代 JavaScript 引擎上,
example
的名称(其name
属性 以及出现在堆栈跟踪中的内容)是example
;run_example
的名字是run_example
(是的,真的,这是 ES2015 规范中的新内容)。所以你会看到堆栈跟踪的差异,或者如果代码检查导出函数的name
属性。显然,通过
run_example
调用时,多了一个函数调用,因此多了一个堆栈帧。您的代码可能不关心。
这是一个片段,说明了大多数现代引擎上的 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+ rest 参数差异的示例:
"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;
}