JavaScript -- Node.js和浏览器中的导出(exports)有什么不同?

4

我尝试运行这个短程序,它来自于《JavaScript高级程序设计》中的模块章节。

var weekDay = function() {}();

(function(exports) {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"];

  exports.name = function(number) {
    return names[number];
  };
  exports.number = function(name) {
    return names.indexOf(name);
  };
})(this.weekDay = {});

console.log(weekDay.name(weekDay.number("Saturday")));

正确的输出应该是// -> 星期六

在浏览器中可以完美运行。然而,当我尝试在Node解释器中运行它时,出现了这个错误:

TypeError: Cannot read property 'name' of undefined

我只能假设这与Node处理exports关键字的方式有关。有人能帮助我至少大致理解这种行为吗?


1
可能是 this.weekDay。尝试将其更改为 weekDay - Louay Alakkad
1
同时第一行是无用的。只需保留 var weekDay; - Louay Alakkad
@AlexanderO'Mara,您介意对那一点进行澄清吗? - Christopher Ronning
这段代码之所以在浏览器中能够工作,是因为“this”是全局对象,并且“this.weekDay”和“weekDay”解析为相同的内容。 - Alexander O'Mara
1
在Node模块中,this是由Node预定义的exports对象。 - Alexander O'Mara
显示剩余3条评论
3个回答

3
尼尔·莱维的答案是正确的,但我也发表了这个答案,因为你在谈论模块。这就是如何将你的代码制作成模块。
//create your module like this and put this module in a separate file (ex. weekDay.js)
var weekDay = (function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

  var name = function(number) {
    return names[number];
  };
  var number = function(name) {
    return names.indexOf(name);
  };

  return {
    number: number,
    name: name
  } 
})(); //it's a self executing function

//exporte module
module.exports = weekDay



//to get your module (in another file)
var weekDayModule = require('./weekDay'); //path to module

console.log(weekDayModule.name(weekDayModule.number('Saturday')));

如果有什么不清楚的地方,请毫不犹豫地要求更多信息 ;) - Nike Sprite

2
在Node.js中,这行代码是:
var weekDay = function() {}();

这段代码只是定义了一个空函数(在你的代码中的{}),并立即运行它,因此会生成未定义的变量weekDay。由于函数体为空(最重要的是没有返回语句),所以它产生了undefined。

要实现您想要的功能,需要将整个定义放在此函数内,并定义要公开的内容,如下所示:

var weekDay = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"];

  var name = function(number) {
    return names[number];
  };
  var number = function(name) {
    return names.indexOf(name);
  };

  return {
    number: number,
    name: name
  }

}();


console.log(weekDay.name(weekDay.number("Saturday")));

这个解决方案实际上是书中使用的原始工作示例。Haverbeke对我写出的另一个版本有这样的评价:“对于更大的模块,将所有导出值收集到函数末尾的对象中变得很麻烦,因为许多导出函数可能很大,而您更愿意在其他地方编写它们。一个方便的替代方法是声明一个对象(通常命名为exports),并在定义需要导出的内容时添加属性。” - Christopher Ronning
@ooronning:检查一下我的答案,这是将模块导出到单独文件的常见方式。 - Nike Sprite

0
将第一行更改为var weekDay = {};,当调用你的iife时,只需将你在第一行创建的weekDay放入其中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接