nodejs学习(一)概念和相关介绍
一.Node.js简介
- node是一款对ES标准实现的JS引擎 - 通过node可以使js在服务器中运行 - node就是一款使用js编写的web服务器 - node底层是使用c++的编写的 - node的中js引擎使用的chrome的v8引擎 - node的特点: 1.非阻塞、异步的I/O(当执行i/操作时,不会阻塞线程) 2.事件和回调函数(当事件触发,执行传递过去的回调函数) 3.单线程(主线程单线程,后台I/O线程池) 4.跨平台
二.node目录结构
三.模块相关
1.模块引用和分类
• 在规范中,定义了require()方法,这个方法接手模块标识,以此将一个模块引入到当前运行环境中。
• 模块引用的示例代码: – var math = require('math');
分类:
核心模块 - http、fs、path、url、net、os、readline、...... - 核心模块在Node.js自身源码编译时,已经编译成二进制文件 - 部分核心模块在Node.js进程启动的时候已经默认加载到缓存里面了 文件模块 - 文件模块可以是:*.js 模块、*.node模块、*.json模块,这些都是文件模块 - 无论从npm上下载的第三方模块还是我们自己编写的模块都是文件模块
2.模块定义和加载
• 在运行环境中,提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一的导出的出口。 • 在模块中还存在一个module对象,它代表模块自身,而exports是module的属性。 • 在Node中一个文件就是一个模块。 • 从npm上下载的一个包(可能是由多个文件组成的一个实现特定功能的包)也是一个模块 • 任何文件或目录只要可以被Node.js通过`require()`函数加载的都是模块 • 每个模块就是一个独立的作用域,模块和模块之间不会互相"污染" • 我们可以通过编程的方式,指定某个模块要对外暴露的内容(其实就是指定require的返回值,通过require的返回值对外暴露指定内容)。
这个对外暴露内容的过程也叫"导出" `module.exports`
加载
1.无论是核心模块还是文件模块加载都是采用`require('标识符')`来加载
2.核心模块的加载速度是最快的
3.无论是 核心模块 还是 文件模块,加载过一次后都会缓存起来,第二次加载(第二次require)的时候直接从缓存中读取即可。
所以模块中的代码只在第一次加载的时候执行一次,这点要注意。 3.核心模块只能通过 "模块名称" 来加载,例如:`require('模块名称')` 4.文件模块可以通过 require 指定路径的方式来加载(路径可以是文件路径 或 目录) - `require('./a/b.js')` 通过指定相对路径来加载模块 - `require('/a/b.js')` 或 `require('c:\a\b.js')` 通过指定绝对路径来加载 - 注意:`require('')`加载模块的时候,相对路径永远相对于当前模块,不受node命令执行的路径影响。 5.通过路径的方式加载文件模块时,文件的后缀可有可无
- 省略后缀名后,Node.js默认会以:.js、.node、.json的顺序来加载(依次拼接不同的后缀,查找并尝试加载)。 - 建议:始终加上后缀。
6.模块的加载是同步的
注意:
require 加载模块时做了2件事 1. 执行了模块中的代码 2. 返回了模块中对外暴露的内容(可能是对象、函数等等)
3.模块使用
使用方法:
方法一:
- 导出变量和函数 - 使用 exports - 例子: exports.属性 = 属性值; exports.方法 = 函数;
方法二: - 使用module.exports - 例子: module.exports.属性 = 属性值; module.exports.方法 = 函数; module.exports = {};
关于
1.在每个模块中module表示当前模块对象, 里面保存了当前模块对象的各种信息 2.module.exports 其实就是 require()加载模块时的返回值 3. exports 就是module.exports的一个引用 exports = module.exports; 特别注意:最终暴露给require的返回值的是:module.exports, 而不是exports
源码:
// To illustrate(说明) the behavior, imagine this hypothetical implementation of require(), which is quite similar to what is actually done by require(): function require(...) { var module = { exports: {} }; ((module, exports) => { // Your module code here. In this example, define a function. function some_func() {}; exports = some_func; // At this point, exports is no longer a shortcut to module.exports, and // this module will still export an empty default object. module.exports = some_func; // At this point, the module will now export some_func, instead of the // default object. })(module, module.exports); return module.exports; }
示例:
被导入的模块: 2.js
/* 模块化 - 在Node中,一个js文件就是一个模块 - 在Node中,每一个js文件中的js代码都是独立运行在一个函数中 而不是全局作用域,所以一个模块的中的变量和函数在其他模块中无法访问 */
//这种打印的在导入的时候就会被运行 console.log("我是一个模块,我是02.module.js"); /* 我们可以通过 exports 来向外部暴露变量和方法 只需要将需要暴露给外部的变量或方法设置为exports的属性即可 * */ //向外部暴露属性或方法(只有这样,导入模块的代码才能访问当前(被导入)模块的方法和变量) exports.x = "我是模块2的x"; exports.y = "我是模块2的y"; exports.fn = function xx () { };
导入模块的代码: 3.js
//引入其他的模块 /* 在node中,通过require()函数来引入外部的模块 require()可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块 这里路径,如果使用相对路径,必须以.或..开头 使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块 我们使用require()引入外部模块时,使用的就是模块标识,我们可以通过模块标识来找到指定的模块 - 模块分成两大类 核心模块 - 由node引擎提供的模块 - 核心模块的标识就是,模块的名字 文件模块 - 由用户自己创建的模块 - 文件模块的标识就是文件的路径(绝对路径,相对路径) 相对路径使用.或..开头 */ var md = require("./2"); var math = require("./math"); var fs = require("fs"); console.log(md); console.log(math.add(123,456)); //console.log(fs);
exports 和 module.exports的区别:
helloModule.js
/* module.exports.name = "孙悟空"; module.exports.age = 18; module.exports.sayName = function () { console.log("我是孙悟空~~~"); };*/ module.exports = { name:"猪八戒", age:28, sayName:function () { console.log("我是猪八戒"); } };
test.js
var hello = require("./helloModule"); /* exports 和 module.exports - 通过exports只能使用.的方式来向外暴露内部变量 exports.xxx = xxx - 而module.exports既可以通过.的形式,也可以直接赋值 module.exports.xxx = xxxx module.exports = {} */ console.log(hello.name); console.log(hello.age); hello.sayName();
4.模块标识
• 模块标识其实就是模块的名字,也就是传递给require()方法的参数,它必须是符合驼峰命名法的字符串,或者是以.、 ..开头的相对路径、或者绝对路径。
5.模块的实现
• Node中虽然使用的是CommonJS规范,但是其自身也对规范做了一些 舍。 • 在Node中引入模块,需要经历如下3个步骤: – 路径分析 – 文件定位 – 编译执行 • 在Node中,模块分为三类:一类是底层由C++编写的内建模块,一类Node提供的核心模块; 还有一类是用户编写的模块,称为文件模块。
说明:
var a = 10; /* 在node中有一个全局对象 global,它的作用和网页中window类似 在全局中创建的变量都会作为global的属性保存 在全局中创建的函数都会作为global的方法保存 当node在执行模块中的代码时,它会首先在代码的最顶部,添加如下代码 function (exports, require, module, __filename, __dirname) { 在代码的最底部,添加如下代码 } 实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了5个实参 exports - 该对象用来将变量或函数暴露到外部 require - 函数,用来引入外部的模块 module - module代表的是当前模块本身 - exports就是module的属性 - 既可以使用 exports 导出,也可以使用module.exports导出 __filename - 当前模块的完整路径 __dirname - 当前模块所在文件夹的完整路径 * */ //console.log(global.a); /* arguments.callee - 这个属性保存的是当前执行的函数对象 * */ console.log(arguments.callee + ""); console.log(arguments.length); console.log(exports); console.log(module.exports == exports); console.log(__dirname);
6.包结构
• 包实际上就是一个压缩文件,解压以后还原为目录。符合规范的目录,应该包含如下文件:
– package.json 描述文件
– bin 可执行二进制文件
– lib js代码
– doc 文档
– test 单元测试
7.包描述文件
• 包描述文件用于表达非代码相关的信息,它是一个JSON格式的文件 – package.json,位于包的根目录下,是包的重要组成部分。
• package.json中的字段
– name、 description、 version、 keywords、maintainers、 contributors、 bugs、licenses、 repositories、 dependencies、homepage、
os、 cpu、 engine、 builtin、directories、 implements、 scripts、 author、bin、 main、 devDependencies。
8.NPM(Node Package Manager)
• CommonJS包规范是理论,NPM是其中一种实践。
• 对于Node而言,NPM帮助其完成了第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块之间形成了很好的一个生态系统。
9.NPM命令
• npm –v
– 查看版本
• npm
– 帮助说明
• npm search 包名
– 搜索模块包
• npm install 包名
– 在当前目录安装包
• npm install 包名 –g
– 全局模式安装包
• npm remove 包名
– 删除一个模块
• npm install 文件路径
– 从本地安装
• npm install 包名 –registry=地址
– 从镜像源安装
• npm config set registry 地址
– 设置镜像源
读取控制台输入:
var readline = require('readline'); var rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.question('what is your name? \n', function (answer) { console.log('okay, you are ' + answer + '. thank you!'); rl.close(); })