JavaScript未声明直接给变量赋值的相关技术问题解析
参考运行示例代码:
const x = 'xxx'; xy = x + 'yyy'; xy = xy.toUpperCase(); console.log(xy); // => XXXYYY
问题1:为何在未预先声明xy的前提下,依然可以为其赋值?
这是JavaScript非严格模式下的历史兼容行为:当代码执行到没有用var/let/const显式声明的标识符的赋值语句时,JS引擎会自动在全局作用域下,给这个标识符创建一个挂在全局对象(浏览器环境为window、Node.js环境为globalThis)上的可写属性,默认数据描述符为writable: true、enumerable: true、configurable: true,后续读写操作都直接绑定这个全局属性,因此不会抛出未定义的引用错误。
注意:如果代码开启严格模式(在文件头或函数内部声明
'use strict'),给未声明的变量赋值会直接抛出ReferenceError,不会触发自动创建全局属性的兼容逻辑。
问题2:此处的xy属于变量还是常量?
这里的xy完全是全局变量,和常量没有关系。
JS里的常量是特指用const关键字在对应作用域显式声明的标识符,天生具备“声明时必须初始化、禁止重新绑定赋值”的约束;而这个自动生成的xy是全局对象上的普通可读写属性,没有任何常量的限制特性。
问题3:若xy为常量,为何能够为其重新赋值为转换后的大写值?
首先要纠正认知前提:本例中的xy根本不是常量,因此不存在“常量被重新赋值”的矛盾。
如果xy真的是通过const声明的常量,那执行xy = xy.toUpperCase()这行重新赋值代码时,JS引擎会直接抛出TypeError: Assignment to constant variable,根本无法正常输出最终的大写字符串。本例中能重复给xy赋值,本质就是因为它是自动创建的、没有重赋值限制的全局变量,和const声明的常量行为完全不同。
内容的提问来源于stack exchange,提问作者james

