回归 Node (一)

2,616 阅读6分钟
原文链接: zhuanlan.zhihu.com
从第一次接触 Node 到现在,我从 《从零 XXX Node》 到 《Node XXX 实战》的过程中,学会了 Node 的语法、特性和无数的 npm 包。最近翻译了[译] 在你沉迷于包的海洋之前,还是了解一下运行时 Node.js 的本身 ,正如作者所担心的那样,我学习了太多各种包的用法,却忘了 Node 本身该怎么用。这个学习过程就像辩证法所描述的那样——事物的发展是螺旋式上升的,我还是回到开始的原点,只不过这次应该是内容的前进了。作者在原文中提了 50 个问题,那我试着来回答一下吧。

HERE WE GO!

Node.js 和 V8 之间的关系是什么?可以在没有 V8 的情况下运行 Node 吗?

首先 V8 是 JavaScript 的引擎,给 JavaScript 提供了一个良好的运行环境。得益于 V8 的性能,Node 才能大放异彩。这些都能在 Node 的历史中查阅到,那么没有 V8 还能运行 Node 吗,答案是可以的,只需要给 Node 提供足够的资源即可,比如让 Node 运行在 Windows 10 IoT Core

当你在任何一个 Node.js 文件中声明一个全局变量时,它对于所有模块都是真的全局吗?

这里的声明全局变量是和 JavaScript 的 var 比较的,原文其实已经告诉你答案了(how come),Node 每个文件都有自己的作用域,你在文件内通过 var 声明的全局变量只能用在该文件内,不过你可以像 JavaScript 的 window 一样给 global 赋值。

当暴露一个 Node 模块的 API 时, 为什么我们有时候用 exports 有时候用 module.exports?

这个算是初学者都会触及到的一个问题,力推我司 nswbmw科普文

我们可以依赖不使用相对路径的本地文件吗?

大家都应该写过

const myModule = require('../../../index.js');

这样子通过相对路径写出来很丑,也很容易带来写着写着找不到到底在哪一层的问题。它的解决方案很多,可以看这里

可以在同一个应用中使用相同包的不同版本吗?

严格意义上 npm 官方不推荐这么做,一般有这个需求的是开发者,这件事也是引起了一次大讨论,有了相当多的方法来达到不同版本的目标,如果你不想安装额外的模块,可以试试这个方法;模块的话,参考 npm-install-version

什么是事件循环?它是 V8 的一部分吗?

事件循环确实是一个很优秀的设计,很大程度上解决了 JavaScript 单线程所带来的问题。推荐看一下阮老师写的博文,浅显易懂。那么它是 V8 提供的吗?这个问题其实蛮复杂的,我本人也没研究过源码,但是网络上还是有人讨论的,好好看看这个回答吧。

什么是调用栈?它是 V8 的一部分吗?

调用栈说白了就是存放要调用的函数的栈,它将决定函数的执行顺序。它和 JavaScript 的调用栈是一样的,不过在 Node 中,它是由 V8 来处理的。

setImmediate 和 process.nextTick 的区别在哪里?

前者会把函数排在事件队列里 I/O 操作的前面,而后者直接放在了事件队列里第一的位置上。

如何使异步函数返回值?

推荐使用 Promise,石墨文档技术酒馆有文章科普哟。

回调可以与 Promise 一起使用吗?他们还是同一种方式还是两种不同的方式?

当然可以,弄清楚 Promise 原理就知道回调对于 Promise 的重要性。你想让回调和 Promise 只需要判断一下回调是否存在即可。

什么 Node 模块由许多其他 Node 模块实现?

额。。。这个就很多啦。。。。

spawn、 exec 和 fork 的主要区别是什么?

spawn 和 exec 其实区别不大,都是执行 shell 命令,只不过前者返回的是 stream 后者是 buffer。

而 fork 就如 linux 的 fork 一样,它会 new 一个 V8 的实例来执行命令。

集群模块如何工作?它与使用负载均衡有何不同?

集群模块是在一个主机上 fork 一堆 worker 来跑的,而负载均衡是跨主机的。

--harmony-* 标志是什么?

开启 staged 功能,就是已经开发的隐藏功能。

如何读取和检查 Node.js 进程的内存使用情况?

使用

process.memoryUsage()
当调用栈和事件循环队列都为空时,Node 将做什么?

会退出,想深入了解请看这篇文章

什么是 V8 对象和函数模板?

这一块其实涉及到 V8 的模板的概念,C++ 和 JavaScript 的设计理念在函数这里有很大的不同,所以 V8 需要做一些处理。模板是一个上下文中 JavaScript 函数和对象的蓝图,而 V8 则把 C++ 的 DOM 节点通过模板来包装成 JavaScript 的对象。

那么其实也就可以解释什么是对象模板,什么是函数模板了。

顾名思义,对象模板是用来产出对象的,而函数模板则产出函数。有了模板,你就可以实例化 JavaScript 对象或者函数了。

更深入的知识请看这里

什么是 libuv, Node.js 如何使用它?

libuv 是一个可以跨平台的、高性能的、事件驱动的 I/O 库,它给 Node 提供事件循环还有 I/O 操作等等,文件系统和 child process 也是它提供的。

如何使 Node 的 REPL 总是使用 JavaScript 严格模式?

用 --use_strict 参数。

什么是 process.argv? 它拥有什么类型的数据?

process.argv 可以接受命令行的参数,这样子你可以做一个 CLI,瞅瞅这个吧。

在 Node 进程结束之前,我们该如何做最后一个操作?该操作可以异步完成吗?

可以用 process.on('beforeExit', fn) 来执行最后一个操作,弄回调或者 Promise 都可以异步完成。

你可以在 Node REPL 中使用哪些内置命令?

如下:

.break
.clear
.exit
.help
.save
.load
.editor
除了 V8 和 libuv,Node 还有什么其他外部依赖?

还有 http-parser、c-areas、OpenSSL、zlib。

进程 uncaughtException 事件的问题是什么? 它和 exit 事件的区别是什么?

出现这个错误说明代码鲁棒性不够呀,有错误产生但是你的代码没能 catch。exit 是正常的退出,这个不正常。

在 Node’s REPL 中 _ 意味着什么?

就是上个表达式的结果,就酱。


未完待续。