为何隐式变量可配置,显式变量与函数声明却不可?
为什么隐式全局变量的
configurable为true,而var声明的全局变量(及函数声明)为false? 这问题问到点子上了!核心原因其实是全局成员的创建机制完全不同,咱们一步步拆解:
1. 隐式全局变量:本质是给全局对象“手动加属性”
当你直接写foo = ''时,在浏览器环境下等价于window.foo = ''——这就是个普通的对象属性赋值操作。根据ES规范,通过这种方式添加的对象属性,默认的属性描述符就是:
configurable: trueenumerable: truewritable: true
所以你用Object.getOwnPropertyDescriptor拿到的结果自然是configurable: true,这类属性可以被随意删除、修改描述符。
2. var声明的全局变量:引擎的“特殊绑定流程”
用var bar = ''声明全局变量时,这属于JS引擎的变量声明绑定流程。虽然最终也会成为window的属性,但这个过程是规范专门定义的:引擎会强制把该属性的configurable设为false,同时保留enumerable和writable为true。
这么设计的目的很实际:避免var声明的全局变量被意外删除(毕竟configurable: false的属性无法用delete操作符移除),保证变量声明的稳定性。
3. 函数声明的情况和var一致
你问题里提到的函数声明,其实和var是一个逻辑:全局作用域下的函数声明也是通过绑定机制创建的,所以它的configurable同样是false(另外函数声明的enumerable默认是false,这是和var的小区别)。
直观验证一下差异
咱们用delete操作符试试,就能立刻看到区别:
// 隐式变量:可以被删除 foo = ''; delete window.foo; // 返回 true console.log(window.foo); // undefined // var声明的变量:无法被删除 var bar = ''; delete window.bar; // 返回 false console.log(window.bar); // '' // 函数声明:同样无法被删除 function baz() {} delete window.baz; // 返回 false console.log(window.baz); // ƒ baz() {}
总结一下
一句话说清:
隐式全局变量是普通对象属性赋值,遵循默认的属性描述符规则;而
var声明和函数声明是JS引擎通过变量绑定机制创建的全局成员,规范强制将其configurable设为false,以此保障声明的成员不会被轻易移除。
内容的提问来源于stack exchange,提问作者Ben Aston
相关产品推荐
相关产品推荐

