Node.js学习笔记(二)

今天的内容涉及Node的原理、运行机制和CommonJS的内容,会有点沉闷,也会有点困难,建议像我同样作一些笔记。

模块

在开发大型应用的时候,咱们经常会用到全局变量,例如:var s="Hello"。可是,当咱们的应用愈来愈大时,咱们可能会不当心重复用了几个相同的变量或者函数名,这就会给咱们的应用形成麻烦。为了解决这个困难,因而提出了模块的概念。模块是一种代码的组织形式,就是把实现不一样功能的JS代码分开来写,把相同名字的函数或变量存在不一样的模块中,这样就能够避免相同名的函数或变量发生冲突了。编程

同时,模块还能够提升代码的可维护性。由于你只要关心写好当前的模块,而没必要担忧会污染或影响到别的模块,模块之间都是隔离的。数组

在上一节的例子中,咱们编写了一个hello.js的代码。在这里,咱们把它修改一下:闭包

'use strict';

var s="Hello";

function greet(name){
  console.log(s + "," + name + "!");
}

module.exports=greet;

这里,咱们用module.exports向外输出了一个变量。这个变量就是这个模块与外界的一个出口。这个变量能够是函数、对象、数组编程语言

既然有输出,就要有接口。咱们再建立一个main.js:函数式编程

'use strict';

//引入hello模块:
var heat=require('./hello');
var s='Michael';

heat(s);   //Hello,Michael!

这里,咱们用require函数引入了hello模块。main.js中,变量heat就是在hello.js中暴露的greet函数。接下来heat(s)`就是直接使用它了。函数

Commonjs规范和Node的内部运行

这种模块加载的方式被称为Commonjs规范,除了这种规范以外,还有ES六、AMD、CMD,这里不细谈,我也还没学到,这里只谈谈Commonjs和之前学的闭包知识。网站

在上文中,咱们提到了全局变量的冲突。正如咱们在上面的例子中,两个js文件都声明了变量s,可是并无发生冲突,仍然是按照咱们的意愿来执行的,这就是Node实行了模块的隔离。ui

隔离的原理

Node可以实现模块和变量的隔离,是由于闭包。

JS是一种函数式编程语言,它支持闭包,若是咱们用函数把某个变量包起来,这个变量就变成了函数内部的局部变量了。而咱们知道,闭包中只要这个函数的生命周期没有结束,这个变量也就能够一直存在,而不会受到其余函数外的其余变量的影响。code

咱们以上面的例子来解释,在hello模块中,s="hello"被保存了起来,只对外开了一个口:module.exports=greet,在函数greet中,包含有变量s,因此”s=hello”能一直被保存起来,直到greet在main模块中被引用。对象

这里有一个问题,咱们说须要一个函数才能造成闭包,可是咱们的代码并无这个函数呀?这就是Node作的工做了,Node帮咱们在内部包装了hello模块:

(function(){
  var s="Hello";
  function greet(name){
    console.log(s + "," + name + "!");
  }
})()

所以,s就变成了匿名函数的内部局部变量,后来加载的其余模块中即便也有s变量,也不会影响到这个s变量。

模块的输出

在Node中有一个module对象,让咱们来看看模块的输出过程:

var module={
  id:'hello',
  exports:{}
};
var load=function(module){
  //读取的hello.js代码
  function greet(name){
    console.log( "Hello," + name + "!");
  }
  module.exports=greet;
  //hello.js代码结束
  return module.exports;
};
var exported=load(module);
//保存module
save(module,exported);

在咱们的hello模块中,咱们经过module.exports=greet把一个变量传给了Node,而module其实是Node准备阶段的一个变量,并且也是做为load函数的一个参数被保存了下来。每当咱们使用module.exports时,Node就把一条module按模块分类存了起来,这些module都被保存在了一块儿。

当咱们在main模块中想要用到hello模块时,咱们又使用require()来让Node帮咱们在找到id为hello的module传递给咱们。这样,咱们就拿到了hello的模块输出。

Node的运行参考了 模块—廖雪峰的官方网站,实在看的我也有点绕,不过Node处理模块的运行原理咱们如今看个大概暂时就够了,等学完主体内容再来细细分析。

两种输出方式

咱们能够经过两种方式输出模块:

方法一:

module.exports={
  hello:hello,
  greet:greet
}

方法二:

exports.hello=hello;
exports.greet=greet;

可是你不能直接对exports赋值:

exports={
  hello:hello,
  greet:greet
}
实践证实,使用 module.exports=xxx的方式赋值更好。具体缘由一样涉及到Node的内部处理。有兴趣的同窗能够参考上面的那篇文章。
相关文章
相关标签/搜索