Deno 和 Node.js 区别
与 Node.js 的比较
Deno 和 Node.js 都是基于 Google V8 JavaScript 引擎
构建的运行时。
它们都具有内部事件循环,并提供了用于运行脚本和各种系统实用程序的命令行界面。
项目 | Node.js | Deno |
---|---|---|
API 引用方式 | 模块导入 | 全局对象 |
模块系统 | 同时支持 CommonJS 和 ES Module |
使用 ES Module 作为默认模块系统,不支持 require() |
安全 | 默认无限制,但是可以设置 | 默认全限制,需要显式指定文件、网络和环境权限。允许控制文件系统和网络访问,以运行沙盒代码。 |
Typescript | 通过第三方支持(如ts-node ) |
原生默认支持 |
包管理 | npm +node_modules |
原生支持, Deno 同时承担了运行时和包管理器的角色 |
异步操作 | 默认回调,并支持 Promise | 默认 Promise,Deno 没有历史包袱,所以可以使用最新的方式 |
包分发 | npmjs.com 或 任意git仓库 |
import url ,使用 URL 来加载本地或远程依赖项,类似于 browsers。 |
工具箱 | 通过第三方支持 (gulp /eslint /babel 等 |
原生支持一些工具 |
内置 API 引用方式不同
node 模块导入
node 内置 API 通过模块导入的方式引用,例如:
const fs = require("fs");
fs.readFileSync("./data.txt");
deno 全局对象
而 deno 则是一个全局对象 Deno 的属性和方法:
Deno.readFileSync("./data.txt");
查看 deno 有哪些方法
我们可以通过 repl 看一下:
deno
或 deno repl
进入 repl 后,输入 Deno
回车(相当于查看 Deno
类,不理解类和示例的请自己补习下),
我们可以看到:
{
Buffer: [Function: Buffer],
readAll: [AsyncFunction: readAll],
readAllSync: [Function: readAllSync],
writeAll: [AsyncFunction: writeAll],
writeAllSync: [Function: writeAllSync],
build: {
target: "x86_64-pc-windows-msvc",
arch: "x86_64",
os: "windows",
vendor: "pc",
env: "msvc"
},
chmodSync: [Function: chmodSync],
chmod: [AsyncFunction: chmod],
chownSync: [Function: chownSync],
chown: [AsyncFunction: chown],
customInspect: Symbol(Deno.symbols.customInspect),
inspect: [Function: inspect],
copyFileSync: [Function: copyFileSync],
copyFile: [AsyncFunction: copyFile],
...
}
模块系统
模块系统是 deno 和 node 差别最大的地方,也是 deno 和 node 不兼容的地方。
- node 采用的是 CommonJS 规范,
- deno 采用的 ES Module 的浏览器实现。
ES Module 的浏览器实现
ES Module 大家都熟,但其浏览器实现可能大家还不是很熟悉:
<body>
<!-- 注意这里一定要加上 type="module" -->
<script type="module">
// 从 URL 导入
import Vue from "https://unpkg.com/vue@2.6.11/dist/vue.esm.browser.js";
// 从相对路径导入
import * as utils from "./utils.js";
// 从绝对路径导入
import "/index.js";
// 不支持
import foo from "foo.js";
import bar from "bar/index.js";
import zoo from "./index"; // 没有 .js 后缀
</script>
</body>
deno 的模块规范
deno 完全遵循 es module 浏览器实现,所以 deno 也是如此:
// 支持
import * as fs from "https://deno.land/std/fs/mod.ts";
import { deepCopy } from "./deepCopy.js";
import foo from "/foo.ts";
import "http://deno.axihe.com/demo/hello.ts";
// 不支持
import foo from "foo.ts";
import bar from "./bar"; // 必须指定扩展名
最大的不同:
- 可以通过 import url 直接引用线上资源;
- 资源不可省略扩展名和文件名。
安全
Node 默认有很多权限,
Deno 默认屏蔽所有可能危险的权限,需要指定。
对程序来说,写项目基本没有区别,可以 deno run -A xxx
即可
兼容浏览器 API
Deno 的设计,通过与浏览器 API 保持一致,来减少大家的认知。
概念上兼容,模块系统,从上面介绍看出 deno 是完全遵循浏览器实现的;
默认安全,当然也不是自己创造的概念,w3c 早已做出浏览器权限的规定,我们在做小程序的时候尤为明显,需要获取各种权限;
对于异步操作返回 Promise;
使用 ArrayBuffer 处理二进制;
等等…
存在 window 全局变量
console.log(window === this, window === self, window === globalThis);
实现了 WindowOrWorkerGlobalScope
的全部方法
具体方法列表,我们可以参考:lib.deno.shared_globals.d.ts 和 lib.deno.window.d.ts
// 请求方法
fetch("https://baidu.com");
// base64 转化
let encodedData = btoa("Hello, world"); // 编码
let decodedData = atob(encodedData); // 解码
// 微任务
queueMicrotask(() => {
console.log(123);
});
// 等等。..
总体而言,如果服务端和浏览器端存在相同概念,deno 就不会创造新的概念。
这一点其实 node 也在做,新的 node 14.0 CHANGELOG 就也提及要实现 Universal JavaScript 和 Spec compliance and Web Compatibility 的思想,大趋势。
支持 Typescript
不管你喜欢与否,很多框架都上了 TS,国外的开发者,TS 的普及率已经非常广了,基本属于必学的了。
// index.ts
let str: string = "王境泽定律";
str = 132;
运行
> deno run index.ts
error TS2322: Type '123' is not assignable to type 'string'.
► file:///Users/Administrator/Desktop/index.ts:2:1
2 str = 123
~~~
没有 node_modules
deno 没有 node_modules,我们先看下面的例子
// index.js
import { white, bgRed } from "https://deno.land/std/fmt/colors.ts";
console.log(bgRed(white("hello world!")));
运行
> deno run index.js
Download https://deno.land/std/fmt/colors.ts
Compile https://deno.land/std/fmt/colors.ts
hello world!
我们看到其有 Download
和 Compile
两个步骤。
并不会每次都有 Download
和 Compile
两步的。
当你第二次再运行的时候,就会发现并不会再有 Download
和 Compile
两个步骤了:
> deno run index.js
hello world!
更多的 Deno 可能会有的问题,参考 Deno 常见问题
参考
- https://mp.weixin.qq.com/s?src=11×tamp=1590080202&ver=2352&signature=i1UYctaDAYhTcQJbeTuOUKsMfBAM5YAyqX29M3bO-zs-Yd9k5HXbBZG4nW4a4EGTnkB03ekTfxb9I473-xmPh8LgohYBy4q469Tb1PD2sQbVb3Y5mXIGmA*35KLBJ9&new=1