Node程序传递参数
在某些情况下执行node程序的过程中,我们可能希望给node传递一些参数:
node index.js env=development xiaoming
我们可以通过process内置对象中获取参数,如果我们直接打印这个内置对象,它里面包含很多信息,比如版本、操作系统等。
process {
version: 'v14.15.0',
versions: {
node: '14.15.0',
v8: '8.4.371.19-node.17',
uv: '1.40.0',
zlib: '1.2.11',
brotli: '1.0.9',
ares: '1.16.1',
modules: '83',
nghttp2: '1.41.0',
napi: '7',
llhttp: '2.1.3',
openssl: '1.1.1g',
cldr: '37.0',
icu: '67.1',
tz: '2020a',
unicode: '13.0'
},
arch: 'x64',
platform: 'win32',
release: {
name: 'node',
lts: 'Fermium',
sourceUrl: 'https://nodejs.org/download/release/v14.15.0/node-v14.15.0.tar.gz',
headersUrl: 'https://nodejs.org/download/release/v14.15.0/node-v14.15.0-headers.tar.gz',
libUrl: 'https://nodejs.org/download/release/v14.15.0/win-x64/node.lib'
},
_rawDebug: [Function: _rawDebug],
moduleLoadList: [
'Internal Binding stream_wrap',
'Internal Binding tcp_wrap',
'Internal Binding pipe_wrap',
'NativeModule internal/stream_base_commons',
... 9 more items
],
binding: [Function: binding],
_linkedBinding: [Function: _linkedBinding],
_events: [Object: null prototype] {
newListener: [Function: startListeningIfSignal],
removeListener: [Function: stopListeningIfSignal],
warning: [Function: onWarning],
SIGWINCH: [Function (anonymous)]
},
_eventsCount: 4,
_maxListeners: undefined,
domain: null,
_exiting: false,
config: {
target_defaults: {
cflags: [],
default_configuration: 'Release',
defines: [],
include_dirs: [],
libraries: []
},
variables: {
asan: 0,
build_v8_with_gn: false,
coverage: false,
v8_trace_maps: 0,
v8_use_siphash: 1,
want_separate_host_toolset: 0
}
},
dlopen: [Function: dlopen],
uptime: [Function: uptime],
_getActiveRequests: [Function: _getActiveRequests],
_getActiveHandles: [Function: _getActiveHandles],
reallyExit: [Function: reallyExit],
_kill: [Function: _kill],
hrtime: [Function: hrtime] { bigint: [Function: hrtimeBigInt] },
cpuUsage: [Function: cpuUsage],
resourceUsage: [Function: resourceUsage],
memoryUsage: [Function: memoryUsage],
kill: [Function: kill],
exit: [Function: exit],
openStdin: [Function (anonymous)],
allowedNodeEnvironmentFlags: [Getter/Setter],
assert: [Function: deprecated],
features: {
inspector: true,
debug: false,
uv: true,
ipv6: true,
tls_alpn: true,
tls_sni: true,
tls_ocsp: true,
tls: true,
cached_builtins: true
},
_fatalException: [Function (anonymous)],
setUncaughtExceptionCaptureCallback: [Function: setUncaughtExceptionCaptureCallback],
hasUncaughtExceptionCaptureCallback: [Function: hasUncaughtExceptionCaptureCallback],
emitWarning: [Function: emitWarning],
nextTick: [Function: nextTick],
_tickCallback: [Function: runNextTicks],
_debugProcess: [Function: _debugProcess],
_debugEnd: [Function: _debugEnd],
_startProfilerIdleNotifier: [Function (anonymous)],
_stopProfilerIdleNotifier: [Function (anonymous)],
stdout: [Getter],
stdin: [Getter],
stderr: [Getter],
abort: [Function: abort],
umask: [Function: wrappedUmask],
chdir: [Function: wrappedChdir],
cwd: [Function: wrappedCwd],
env: {
ALLUSERSPROFILE: 'C:\\ProgramData',
APPDATA: 'C:\\Users\\hp\\AppData\\Roaming',
},
title: 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe',
argv: [
'D:\\nodejs\\node.exe',
'D:\\qdcode\\node.js\\node传递参数\\01-dome.js'
],
execArgv: [],
pid: 14472,
ppid: 18452,
execPath: 'D:\\nodejs\\node.exe',
debugPort: 9229,
argv0: 'D:\\nodejs\\node.exe',
_preload_modules: [],
mainModule: Module {
id: '.',
path: 'D:\\qdcode\\node.js\\node传递参数',
exports: {},
parent: null,
filename: 'D:\\qdcode\\node.js\\node传递参数\\01-dome.js',
loaded: false,
children: [],
paths: [
'D:\\qdcode\\node.js\\node传递参数\\node_modules',
'D:\\qdcode\\node.js\\node_modules',
'D:\\qdcode\\node_modules',
'D:\\node_modules'
]
},
[Symbol(kCapture)]: false
}
找到其中的argv属性:我们发现他是一个数组,里面包含我们传递的参数。
console.log(process.argv);
[
'D:\\nodejs\\node.exe',
'D:\\qdcode\\node.js\\node传递参数\\01-dome.js',
'env=development',
'xiaoming'
]
全局对象
Node中给我们提供了一些全局对象,方便我们进行一些操作
特殊的全局对象
其中有一些特殊的全局变量,这些全局对象实际上是模块中的变量,只是每个模块都有,看起来像是全局变量;
但是在命令交互中是不可以使用的;
包括:__dirname、__filename、exports、module、require()
__dirname:获取当前文件所在的路径(不包括后面的文件名)
__filename:获取当前文件所在的路径和文件名称(包括后面的文件名称)
console.log(__dirname); //D:\qdcode\node.js\node传递参数
console.log(__filename); //D:\qdcode\node.js\node传递参数\01-dome.js
常见的全局对象
process对象:提供了Node进程中相关的信息:
- 比如Node的运行环境、参数信息;
- 将一些环境变量读取到process的env中;
console对象:提供了简单的调试控制台
定时器参数:在Node中使用定时器有好几种方式:
- setTimeout(callback,delay[,…args]):callback在delay毫秒后执行一次;
- setInterval(callback,delay[,…args]):callback每delay毫秒重复执行一次;
- setImmediate(callback[,…args]):callback I/O事件后的回调的立即执行;
- process.nextTick(callback[,…args]):添加到下一次tick队列中
global和window的区别
在浏览器中,全局变量都是window上的,比如document、setInterval、alert、console等。
在Node中也有一个global属性,看起来它里面也有很多其他对象。
但是在浏览器中执行js代码,如果我们在*范围内通过var定义一个属性,默认会被添加到window对象上
var name = 'zhangsan'
console.log(window.name) //zhangsan
但是在node中,我们通过var定义一个变量,他只是当前模块中有一个变量,不会放到全局中
var name = 'zhangsan'
console.log(window.name) //undefined
模块化开发
事实上模块化开发最终目标是将程序划分成一个个小的结构,这个结构中编写属于自己的逻辑代码,有自己的作用域,不会影响到其他的结构。
这个结构可以将自己希望暴露的变量、函数、对象导出给其他结构使用。
也可以通过某种方法,导入另外结构中的变量、函数、对象等。
上面提到的结构就是模块;安装这种那个结构划分开发程序的过程,就是模块化开发的过程。
模块化已经是js一个非常迫切的需求:
- 但是js本身,知道es才推出了自己的模块化方案;
- 在此之前,为了让js支持模块化,涌现了很多不同的模块化规范:AMD、CMD、CommentJS等。
没有模块化的问题
小明编写的xiaoming.js
var name = '小明'
小红编写的xiaohong.js也使用的name
var name = '小红'
小明又在sayName.js中调用了name变量
console.log(name);
这样的顺序引入js会导致小明的代码被小红的代码覆盖。从而输出错误的信息。
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./xiaoming.js"></script>
<script src="./xiaohong.js"></script>
<script src="./sayName.js"></script>
</head>
这种情况我们可以采用立即执行函数结果(IIFE)
xiaoming.js
var xiaoming = (function(){
var name = 'xiaoming';
return{
name
}
})()
xiaohong.js
var xiaohong =(function(){
var name = 'xiaohong'
return {
name
}
})()
sayName.js
console.log(xiaoming.name); //xiaoming
console.log(xiaohong.name); //xiaohong
使用立即执行函数我们不必关注js引入的顺序
但是这样也有新的问题:
- 我们必须记住每一个模块中返回对象的命名,才能在其他模块使用过程中正确的使用;
- 每个文件中的代码都需要包裹在一个匿名函数中
- 没有合适的规范中,每个人都可能会任意命名、甚至出现模块名称相同的情况。
CommonJS
我们需要知道CommonJS是一个规范,最初提出来是在浏览器以外的地方使用,并且当时被命名为ServerJS,后来为了体现它的广泛性,修改为CommentJS。
- Node是CommentJS在服务器端一个具有代表性的实现。
- Browserify是CommentJS在浏览器中的一种实现;
- webpack打包工具具备对CommentJS的支持和转换;
所以,Node中对CommentJS进行了支持和实现,让我们在开发node的过程中可以方便的进行模块化开发:
- 在Node中每一个js文件都是一个单独的模块;
- 模块中包括CommentJS规范的核心变量:exports、module.exports、require;
- exports和module.exports可以负责对模块中的内容进行导出;
- require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容。
基本使用
Bar.js 暴露方法和变量 可以通过module.exports和exports.属性暴露。
const name = 'xiaoming';
const age = 18;
const sayHello = ()=>{
console.log('hello!!!');
}
console.log(exports) //{} 空对象
//方法一:
module.exports = {
name,age,sayHello
}
//方法二:
exports.name = name;
exports.age = age;
exports.sayHello = sayHello;
Main.js
const Person = require('./Bar')
console.log(Person.name); //xiaoming
console.log(Person.age); //18
Person.sayHello(); //hello!!!
require(’./Bar’)引入的bar其实是Bar.js中暴露出的对象exports的一个浅拷贝(引用赋值)。
当修改bar中的name值时,Bar.js暴露的exports对象中的name也跟着改变。
module.exports和exports的区别
在Node中我们经常使用module.exports导出,这两种方式有什么区别呢?
CommentJS中是没有module.pexorts的概念的,但是为了实现模块的导出,Node中使用的是Module的类,每一个模块都是Module的示例,也就是module。
所以在Node中真正用于导出的其实根本不是exports,而是module.exports。因为module才是导出的真正实现者。
为什么exports也可以导出呢?
这是因为module对象的exports属性是exports对象的一个引用。
也就是说 module.exports = exports
Bar.js
const name = 'xiaoming';
const age = 18;
const sayHello = ()=>{
console.log('hello!!!');
}
const car = '奥迪';
const color = 'red';
const sayRun = () =>{
console.log('红色的奔驰嗖嗖的跑');
}
module.exports = {
car,color,sayRun
}
exports.name = name;
exports.age = age;
exports.sayHello = sayHello;
Main.js
const bar = require('./Bar')
console.log(bar); //{ car: '奥迪', color: 'red', sayRun: [Function: sayRun] }
require的值最终取决于module.exports暴露的对象。当设置了module.exports就不带exports玩了。
强调一次:module.exports = exports 。
Bar.js
//module.exports = exports 先执行的
exports = 123
Main.js
const bar = require('./Bar')
console.log(bar); //{}
初始状态,exports默认为{}空对象。module.exports = exports
exports = 123时,因为123是值传递所以直接把地址改成值。取消了对{}的引用。但是不影响module.exports的指向。