深入理解Nodejs Global 模块
浏览器上有自己的全局对象 window,同理, nodejs 下也有自己的全局对象 global,并且在各个模块下 都可以直接访问 global 对象。
在 nodejs 中,除了可以直接使用 v8 javascript 引擎中所支持的原生 javascript 的函数和对象外,它还追加了一些其他的函数和对象(比如:buffer 对象、require 函数等)。
- buffer 对象: 用于处理二进制数据
- module 对象: 用于访问当前模块的信息
- process 对象: 用于访问进程信息
- console 对象: 用于向控制端输出某些信息
- 6 个计时器相关函数
需要注意的是,可以在不引入模块的情况下直接使用 nodejs 追加的这些函数和对象。
下面将对上面的这些对象和函数的使用进行简单的解释。
buffer 对象
在 es6 之前,原生的 javascript 并没有专门用来处理二进制数据的机制,所以为了方便地处理二进制数据,nodejs 才引入了 buffer 对象。
es6 之后,原生的 javascript 引入了 typedarray,用来处理二进制数据。注意 typedarray 并不是以一个单一的对象的形式而存在,而是以一系列值的类型为 typedarray 的对象而存在。在这一系列对象中,uint8array 对象和 buffer 对象最为相似,但是 buffer 对象更加适用于 nodejs。
buffer 对象的实例很像一个各个元素都是整数的数组,但是与真正的数组的区别在于它的大小固定的(即在实例创建时决定大小),并且为它分配的内存是原生的,并且存在于 v8 的堆内存外。
在 nodejs 6.0 版本之前,是使用 new buffer() 语法来创建一个实例,但是因为一些安全问题,以这种形式创建实例的方法被废除了,取而代之的是一些 buffer 对象的一些静态方法。
创建 buffer 实例
- buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 buffer 实例,如果没有设置 fill,则默认填满 0
- buffer.allocunsafe(size): 返回一个指定大小的 buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据
- buffer.allocunsafeslow(size)
- buffer.from(array): 返回一个被 array 的值初始化的新的 buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)
- buffer.from(arraybuffer[, byteoffset[, length]]): this creates a view of the arraybuffer without copying the underlying memory
- buffer.from(buffer): 复制传入的 buffer 实例的数据,并返回一个新的 buffer 实例
- buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 buffer 实例
const buf1 = buffer.alloc(5); const buf2 = buffer.allocunsafe(5); const buf3 = buffer.from([1, '2a', 230]); const buf4 = buffer.from('abcdggg'); console.log(buf1); // <buffer 00 00 00 00 00> console.log(buf2); // <buffer b8 ed a3 80 58> (这只是一种可能的结果) console.log(buf3); // <buffer 01 00 e6> console.log(buf4); // <buffer 61 62 63 64 67 67 67> console.log(buf4.tostring()); // abcdggg buf2.fill(0); console.log(buf2); // <buffer 00 00 00 00 00>
上面讲的不太清楚(以后再优化),因为我是初学,typedarray 都没玩过呢!
但是放心,大腿在这呢 — node源码解析 – buffer
源码链接:
buffer.bytelength(string[, encoding]):
返回 string 的实际的字节长度(注意不是字符长度)
let str1 = 'a'; let str2 = '小'; let str3 = 'aa'; let str4 = '小a'; console.log(str1.length); // 1 console.log(buffer.bytelength(str1)); // 1 console.log(str2.length); // 1 console.log(buffer.bytelength(str2)); // 3 console.log(str3.length); // 2 console.log(buffer.bytelength(str3)); // 2 console.log(str4.length); // 2 console.log(buffer.bytelength(str4)); // 4
上面的汉字 小 的 utf-8 码正好占用三个字节(\xe5\xb0\x8f),所以才会有上面的结果。
buffer.concat(list[, totallength]):
连接多个 buffer 实例或 uint8array 实例,并返回一个新的 buffer 实例
const buf1 = buffer.alloc(10); const buf2 = buffer.alloc(14); const totallength = buf1.length + buf2.length; console.log(totallength); // 24 const buf = buffer.concat([buf1, buf2], totallength); console.log(buf.length); // 24
buffer.isbuffer(obj):
判断一个对象是不是 buffer 实例
buffer.isencoding(encoding):
判断是否支持指定的编码方式
console.log(buffer.isencoding('utf8')); // true console.log(buffer.isencoding('utf9')); // false
buffer.poolsize:
指定预分配的字节数的大小,默认为 8192(即 8 kb)
buffer.prototype.buffer:
一个指向 arraybuffer 的引用
const arraybuffer = new arraybuffer(16); const buffer = buffer.from(arraybuffer); console.log(buffer.buffer === arraybuffer); // true
buffer.prototype.equals(otherbuffer):
比较两个 buffer 实例是否拥有完全相同的 bytes
const buf1 = buffer.from('hello'); const buf2 = buffer.from('hello'); console.log(buf1.equals(buf2)); // true
用于迭代的方法
- buffer.prototype.entries()
- buffer.prototype.keys()
- buffer.prototype.values()
buffer.prototype.fill(value[, offset[, end]][, encoding]):
用指定的值填充满 buffer 实例
const b = buffer.allocunsafe(25).fill('abc呵呵'); // 注意下面因为不够容纳全部的汉字字节,所以乱码 console.log(b.tostring()); // abc呵呵abc呵呵abc呵�
buffer.prototype.includes(value[, byteoffset][, encoding])
buffer.prototype.indexof(value[, byteoffset][, encoding])
buffer.prototype.tojson():
返回一个 json 对象
当 json.stringify(buf) 的参数为一个 buffer 实例时,会隐式地调用上面的方法
const b = buffer.from('hell') let json = b.tojson(); console.log(json); // { type: 'buffer', data: [ 104, 101, 108, 108 ] } console.log(json.stringify(b)); // {"type":"buffer","data":[104,101,108,108]}
buffer.prototype.tostring([encoding[, start[, end]]]):
以指定的 encoding 解码 buffer 实例,返回解码后的字符串
const buf = buffer.from([104, 101, 108, 108]); console.log(buf.tostring()); // hell console.log(buf.tostring('base64')); // agvsba== console.log(buf.tostring('hex')); // 68656c6c
字符串不能被修改,但是 buffer 实例却可以被修改。
const buf = buffer.from('abcd'); console.log(buf.tostring()); // abcd buf[1] = 122; console.log(buf.tostring()); // azcd
buffer.prototype.write(string[, offset[, length]][, encoding]):
将指定字符串写入到 buffer 中
const buf = buffer.from('abcdefg'); console.log(buf); // <buffer 61 62 63 64 65 66 67> console.log(buf.tostring()); // abcdefg buf.write('和', 1); console.log(buf); // <buffer 61 e5 92 8c 65 66 67> console.log(buf.tostring()); // a和efg
好了,还有一堆方法就不一一列出来了,buffer 就到这里了。
module 对象
在使用 require 函数加载模块文件时,将运行该模块文件中的每一行代码
模块在首次加载后将缓存在内存缓存区中,所以对于相同模块的多次引用得到的都是同一个模块对象,即对于相同模块的多次引用不会引起该模块内代码的多次执行。
在编译的过程中,node 会对获取的 javascript 文件内容进行头尾包装!
// 包装前 module666.js const pi = 6666; module.exports = pi; // 包装后,注意下面不是立即执行函数 (function(exports, require, module, __filename, __dirname) { const pi = 6666; module.exports = pi; });
__filename & __dirname
- __filename: 返回当前模块文件的绝对路径(带文件名)
- __dirname: 返回当前模块文件所在目录的绝对路径
// 1.js console.log(__filename); // c:\users\percy\desktop\nodejs\1.js console.log(__dirname); // c:\users\percy\desktop\nodejs
process 对象
process 对象是 nodejs 的一个全局对象,提供当前 nodejs 进程的信息。
属性
- process.arch: 返回当前处理器的架构
- process.env: 返回一个包含用户环境变量的对象
- process.argv: 返回一个数组,数组的第一个元素总是 node 程序的绝对路径,第二个元素是当前执行脚本的绝对路径
- process.execpath: 返回 node 程序的绝对路径
- process.argv0: 返回 node 程序的绝对路径
- process.pid: 返回当前进程的进程号
- process.platform: 返回当前的系统平台标识符(比如:'darwin', ‘freebsd', ‘linux', ‘sunos' or ‘win32')
- process.version: 返回当前 node 的版本号
- process.versions: 返回一个对象,列出了 nodejs 和其相关依赖的版本号
三个重要的属性
- process.stdin: 返回一个指向标准输入流的可读流(readable stream)
- process.stdout: 返回一个指向标准输出流的可写流(writable stream)
- process.stderr: 返回一个指向标准错误流的可写流(writable stream)
方法
- process.cwd(): 返回进程当前的工作目录
- process.chdir(path): 改变进程当前的工作目录
- process.cpuusage(): 返回当前 cpu 的使用情况
- process.memoryusage(): 返回当前内存的使用情况
- process.uptime(): 返回 node 程序已运行的秒数
- process.nexttick(callback[, …args]): 指定回调函数在当前执行栈的尾部、下一次event loop之前执行
- process.emitwarning(warning[, options]): 触发一个 warning 事件,可以自定义一些警告信息
- process.exit([code]): 立即结束当前进程,但是会触发 process 的 exit 事件
- process.abort(): 立即结束当前进程,不会触发 exit 事件
console.log(process.cwd()); // c:\users\percy\desktop\nodejs process.chdir('../'); console.log(process.cwd()); // c:\users\percy\desktop
process.emitwarning('something happened!', { code: 'my_warning', detail: 'this is some additional information' }); process.on('warning', (warning) => { console.log(warning); })
process.on('exit', function(code) { console.log('exit~', code); }); process.exit(); // exit~
process 对象还有一些方法没列出来,因为我现在看不懂怎么用,以后补 >_<
console 对象
这个对象就是用来在控制台下面打印一些信息而已,挑几个有用但没记牢的方法来玩玩。
console.dir(value):
打印一个对象的详细信息
const buf = buffer.from('abcdefg'); console.log(buf); // <buffer 61 62 63 64 65 66 67> console.dir(buf); // buffer [ 97, 98, 99, 100, 101, 102, 103 ]
console.time(label) & console.timeend(label):
用来统计代码执行时间
let label = 'time'; let str = 'hello'; console.time(label); while (str.length < 999999) { str += 'a'; } console.timeend(label); // time: 133.724ms
6 个计时器函数
在浏览器上,就有相应的 4 个计时器函数(setinterval、clearinterval、settimeout、cleartimeout),只不过它们是 window 全局对象的属性。
在 nodejs 中,除过上面的 4 个计时器,还增加了两个(setimmediate,clearimmediate)。
这六个计时器函数被定义在了全局对象 global 下,即可以直接在代码中进行使用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: js实现一个简单的MVVM框架示例
推荐阅读