这一章不写复杂代码,只解决一个最根本的问题:同一门 JavaScript,为什么在浏览器里能用的东西,搬到 Workers 或 Surge 脚本里就报错?搞懂这个,后面少踩很多坑。
一句话目标:
JavaScript(简称 JS)是一门编程语言,最早是为了让网页能动起来、能响应点击而发明的,后来被搬到了越来越多的地方运行。
关键的一点:语言本身在哪儿都一样。语法、数组、对象、函数这些“语言自带的东西”,在浏览器、在服务器、在手机 App 里写出来都是一模一样的。
真正的区别是:每个运行环境会额外送一套自己的“内置工具”。写代码时能用哪些工具,取决于你现在站在哪个环境里。
打个比方:JS 就像同一个人,语言本身是他脑子里的本事,到哪儿都不变;运行环境就是他随身带的工具箱。换一个环境,就是换了一只工具箱——人还是那个人,能干的活却因为工具不同而不同。
| 运行环境 | 它在哪儿 | 特有工具(这个环境才有) | 用来干什么 |
|---|---|---|---|
| 浏览器你现在看的这个页面,就跑在浏览器里 | 网页里面 | document 改页面内容、window 代表浏览器窗口 |
网页前端:页面长什么样、点按钮有什么反应 |
| Node.js读作“诺德 JS”,是让 JS 离开网页、跑在电脑上的环境 | 自己的电脑 / 服务器 | 文件系统 fs,能读写电脑上的文件 |
本地脚本和小工具,比如批量改文件名、处理文件 |
| Cloudflare Workers读作“沃克斯”,是 Cloudflare 公司的边缘服务器 | CF 的边缘服务器(离用户很近的机房) | fetch 事件接收请求、env 里存着 KV、D1 数据库和密钥 |
你的 tg-bot、graintcp 等一堆 Worker 都跑在这里,全天候在网上接活 |
| Surge / Loon / REX 脚本REX 是同类工具,脚本的写法跟 Surge、Loon 相通 | 手机 App 里面 | $httpClient 发网络请求、$request 看请求内容、$done 告诉 App“处理完了” |
去广告、改返回结果、自动签到这类脚本 |
在 Workers 里写 document,在 Surge 脚本里写 fetch,都会立刻报错,说这个名字“未定义”(英文是 is not defined)。
这不是你的 JS 写错了,而是那个环境的工具箱里,根本没有这件工具。先想“这里是哪种环境、工具叫什么”,能省下大量瞎试的时间。
下面两个框里的代码可以直接改,点运行就会在这台手机的浏览器里真正跑一遍,结果显示在框子下方。先别改,原样各点一次。
console.log 是每个环境都有的基本工具,作用是把括号里的内容打印出来给你看,是学 JS 时最常用的“检查工具”——想知道某一步算出了什么,就打印出来看一眼。"object"(意思是“它是一个对象,真实存在”)。为什么这里查得到?因为这个页面本身就跑在浏览器环境里,document 是浏览器工具箱里的工具,当然在。把同一行代码放到 Workers 里运行,就会报错——那里没有页面,自然也没有 document。试着玩一下:把练习 ① 里的“你好”换成别的话再运行;或者新写一行 console.log(typeof fetch); 加到练习 ② 里——浏览器里也有 fetch,看看它打印什么。如果写错了也不怕,出错时下方会给出中文说明。
点一个选项,立刻判对错。选错了会告诉你错在哪,可以重选;选对了会告诉你为什么对。
在 tg-bot 里写代码时,想当然地用了 document 去改“页面”——结果报错。原因现在你已经知道了:tg-bot 跑在 Cloudflare Workers 里,那里根本没有页面,工具箱里没有 document 这件工具。这不是语法错,是环境认错了。
“取现在的时间”这件事,浏览器和 Workers 的写法完全一样,因为这是语言本身的能力:
var 现在 = new Date(); // new Date() 就是“拿到现在的时间”,哪种环境都这么写
但“把数据存下来”就不一样了,每个环境用自己的工具:
localStorage // 浏览器存数据的地方 env.你的KV // Workers 用 KV 存数据(env 是放 KV、密钥的工具箱格子) $persistentStore // Surge / Loon 存数据的工具
记住这组对照,以后写“存数据”之前先问自己:我现在站在哪个环境?
以后给它们写代码或改代码,先认环境再找工具:Workers 的活找 fetch、env;Surge / Loon 的活找 $httpClient、$done。
JS 是同一门语言、同一个“人”;浏览器、Node.js、Workers、Surge / Loon 只是四只不同的工具箱——写代码前先认环境,报错“未定义”先想“是不是这个工具箱里没有这件工具”。