JavaScript异步函数变量访问方法及异步函数读取外部变量时selectors未定义问题解决方案
先解决你碰到的「selectors is not defined」错误
看你贴的代码,有几个关键问题会直接导致这个错误,咱一个个说:
fs模块未导入:在index.js里你用了fs.readFileSync,但Node.js里必须先导入模块才能使用!得在文件最顶部加上这行:import fs from 'fs'; // 要是你用CommonJS规范就写 const fs = require('fs');没导入的话,这行代码直接报错,后面的
selectors变量根本没机会被定义,调用getSpecs(selectors)的时候自然就提示selectors is not defined了。顶层
await的限制:你在index.js里直接写了await getSpecs(selectors),但await只能在async函数内部使用(Node.js 14.8之后支持顶层await,但前提是你的项目配置成ES模块,比如package.json里加"type": "module")。要是环境不支持,必须把代码包在一个异步函数里:import { getSpecs } from "./getSpecs.js"; import fs from 'fs'; async function init() { let file = fs.readFileSync('selectors.json'); let selectors = JSON.parse(file); await getSpecs(selectors); } init();要是不管这个,代码会抛语法错误,同样会导致
selectors没被正确定义就传进函数。未声明的变量
var1:在getSpecs.js里你用了var1但没加let/const/var,这会让它变成全局变量,虽然不是直接导致selectors错误,但绝对是不良编码习惯,赶紧改成:export let getSpecs = async function(selectors) { const var1 = document.querySelector(selectors.seller).innerText; // ...其他代码 }另外提一嘴:
document是浏览器环境的对象,要是你这代码在Node.js环境运行,document会直接未定义!如果是做爬虫,得用Puppeteer这类工具来操作DOM,不能直接用document哈。
异步函数的变量作用域:你可能的误区&正确用法
其实异步函数(async function)的作用域规则和普通函数几乎一模一样,你之前的困惑大概率是对异步执行的逻辑有点混淆,咱理清楚:
1. 访问外部变量(闭包)
异步函数完全可以像普通函数一样访问外部作用域的变量,只要变量在函数定义时是可访问的:
const externalVar = "我是外部变量"; async function asyncFunc() { console.log(externalVar); // 完全能正常访问 } asyncFunc();
但要注意变量的生命周期,如果外部变量在异步函数执行前被销毁或重新赋值,会影响最终的访问结果。
2. 通过参数传递变量
这就是你代码里用的方式,也是最清晰、最不容易出错的——把需要的变量作为参数传给异步函数,就像你调用getSpecs(selectors)那样。只要参数传递正确,函数内部就能直接用这个参数,完全没作用域问题。
3. 获取异步函数内部的变量
异步函数内部用let/const声明的变量,作用域仅限函数内部,和普通函数一样。要是想在外部拿到内部变量,得通过return返回,然后用await或者.then()接收:
async function getSpecs() { const innerVar = "我是内部变量"; return innerVar; } // 外部获取的正确方式: async function main() { const result = await getSpecs(); console.log(result); // 输出"我是内部变量" } main();
常见误区避坑
- 误以为异步函数不能访问外部变量:错啦!只要变量在函数的作用链上,异步函数和同步函数的访问规则完全一致。
- 忽略顶层await的限制:在Node.js或浏览器的顶层作用域直接用
await会报错(除非环境明确支持),必须包在async函数里。 - 未声明变量导致全局污染:像你代码里的
var1,不声明会变成全局变量,很容易引发各种意外问题,一定要养成声明变量的习惯。
内容的提问来源于stack exchange,提问作者Cosmos

