作者解释了需要函数here的最小实现,如下所示:
function require(name) {
var code = new Function("exports", readFile(name));
var exports = {};
code(exports);
return exports;
}
console.log(require("weekDay").name(1));
// → Monday
我很难理解到底发生了什么,主要是因为这个例子不完整。目前,我已接受readFile()
以字符串格式返回代码。这部分让我很困惑:为什么var exports
被传递到代码中,它在做什么,为什么要返回? exports
对象如何返回readFile
已检索到的代码?
答案 0 :(得分:6)
new Function("exports", body)
将创建一个匿名函数,该函数接受一个参数(exports
)并执行body
中的代码。
将传递给函数体的exports
作为空对象开始,目的是模块体将用它想要向世界其他地方公开的东西填充它。然后执行该函数(我们传入我们的exports
对象)。最后,返回模块导出的内容。
这是一个更完整的例子:
fakeFileSystem = {
"weekDay.js": " \
var days = [ \
'Sunday', \
'Monday', \
'Tuesday', \
'Wednesday', \
'Thursday', \
'Friday', \
'Saturday' \
]; \
function name(dayNo) { \
return days[dayNo]; \
} \
exports.name = name; \
"
};
function require(name) {
var code = new Function("exports", fakeFileSystem[name + ".js"]);
var exports = {};
code(exports);
return exports;
}
console.log(require("weekDay").name(1));
// → Monday
这是有效的,因为code
的构造就像它是这个函数一样:
function(exports) {
var days = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
function name(dayNo) {
return days[dayNo];
}
exports.name = name;
}
我们将{}
传递给此函数,并将其修改为
{
name: function(dayNo) {
return days[dayNo];
}
}
其中days
在闭包中被捕获,但对外界不可见。这使我们只能访问模块中明确添加到exports
的内容(如name
),同时隐藏所有不属于days
的内容。{ p>
答案 1 :(得分:2)
此示例需要了解函数构造函数。
这可能会有所帮助:
$ node
> f = new Function("x", "return x + 2");
[Function]
> f(8)
10
在您的示例中,函数的主体是文件中的代码,您将在其中看到变量exports
的属性的赋值。那么exports
是什么?这是一个最初为空的对象。调用时,模块的主体将“填充”。在调用code(exports)
之后,您将拥有一个包含许多好东西的填充对象,该对象从require
返回。
示例:
假设文件包含
var x = 3
exports.y = 10 * x
然后你的调用会传入一个空对象,但是执行该函数会将y
属性添加到对象中,然后你会回来
{y: 30}