js如何定义全局变量-三种原生写法适配不同代码场景
上周改老旧前端页面的时候,卡在js如何定义全局变量这个基础问题上,明明之前写过无数次,换了嵌套函数之后变量死活读不到,对着控制台爆红的报错愣了快半小时,一度怀疑自己最基础的语法都记错了。
最开始一直抱着很粗浅的认知,觉得只要不用函数包裹,直接写变量就是全局变量,不管用var、let还是const都通用。平时写简单单行代码确实没问题,页面简单交互也从来没出过差错,就一直默认这个写法百分百靠谱,从来没深究过作用域的区别,也没去看过变量到底挂载在了哪个对象上面。
踩第一个大坑。
写嵌套函数的时候,在函数内部用var直接声明变量,跳出函数之后再调用,控制台直接提示变量未定义,当时第一反应是代码拼写错了,反反复复核对变量名五六遍,删掉空格、调整代码换行位置,折腾好久才搞明白,函数内部用var声明的变量属于函数局部作用域,压根透不到全局,之前无脑用var的习惯完全行不通,这是我第一次打破最初片面的认知。
之后又试着不写任何关键字,直接裸写变量赋值,比如a=10,没想到这个写法居然能成功变成全局变量,不管在哪个函数里赋值,外部都能正常读取。但随便问了身边前端同事才知道,这种隐式全局变量隐患特别大,项目代码一多,很容易无意间覆盖同名变量,排查bug的时候根本找不到变量被修改的源头,维护起来麻烦得要命,看着简洁实则特别不规范,小demo随便写还行,正式项目里绝对不能这么用。
再后来才摸清window对象挂载的写法,这也是项目里最稳妥的方式。浏览器环境下所有全局变量本身都挂载在window上,直接写window.变量名=值,不管代码写在函数、循环还是任何块级作用域里面,都能稳定成为全局变量,不会被局部作用域隔离。而且这个写法可读性很高,一眼就能分辨出哪些是全局变量,后续团队协作改代码的时候,也不会出现误改全局变量的情况。
let和const是最容易被忽略的点。
之前一直分不清var和let全局声明的区别,直接在代码最外层用let、const定义变量,看着也是全局能用,可实际上这类变量不会挂载到window对象上,在特殊场景比如iframe页面通信、跨窗口调用变量的时候,根本无法读取到这个变量。很多新手只知道外层声明能用,却不知道它不属于window全局,遇到跨页面交互的场景就会直接翻车,我上周的报错本质上也是忽略了这个不起眼的细节。
关掉电脑之后,指尖还停在键盘的回车按键上,脑子里乱糟糟全是各种作用域的边界问题,没有整理任何笔记,也没有刻意记语法规则,只是觉得越是基础的JS语法,越容易凭经验踩坑。