大多数前端开发者都知道在浏览器里全局对象是 window
,这点可以用 Object.is(globalThis, window)
来验证
如果在浏览器的全局环境下定义一个变量,那么它将被自动挂载到 window
对象上
var name = "Mike";
console.log(window.name)
但 let 和 const 却不会这样
let age = 10;
const sex = "Male";
console.log(window.age, window.sex)
1
thinkershare 2023-08-30 17:34:16 +08:00 1
不要用 var 这种垃圾。
|
2
hsfzxjy 2023-08-30 17:35:23 +08:00 via Android
是这样的,而且不只这个差别
|
3
rrfeng 2023-08-30 17:39:50 +08:00
var 就是全局变量,千万别用。
|
4
liberty1900 OP 用惯了了 VS Code ,里面 Cmd + Enter 是 Insert Line Below ,V 站这里直接给我发帖了。。。
|
5
Jirajine 2023-08-30 17:49:17 +08:00 via Android 1
你不用管它有什么区别,你只需要记住 var 是 deprecated ,永远不要使用就行了。
|
6
liberty1900 OP let/const 是 block scope 的,我以前理解所谓 block scope 就是用花括号形成的 scope 比如:
```javascript { let age = 10; console.log(age); // 10 } console.log(age) // undefined ``` 如果我没有显示套上大括号,也就没有了 block scope 但是变量总得有个 scope ,那这个 scope 是不是 global scope 呢?看来我理解错了 |
7
HelloWorld556 2023-08-30 17:54:25 +08:00 1
|
8
chengxy 2023-08-30 17:58:10 +08:00
继续往下,学学 let 和 const 的区别
|
9
Adicwu 2023-08-30 18:01:12 +08:00
这你就得问问变量提升了
|
10
liberty1900 OP @liberty1900 一种合理的解释是 let/const 一定是 block scope 的,即使没有显式用花括号声明也是 block scope, 只是这种 scope 是隐式的,而且和 global scope 有区别,不能混为一谈
|
11
liberty1900 OP @chengxy 我知道 let 和 const 的区别,也知道 const 的局限性以及如何用 Object.create/Object.definedProperties/Object.seal/Object.freeze 来实现不同程度的不可变
|
12
cmdOptionKana 2023-08-30 18:11:06 +08:00
年轻人真幸福啊,没经历过只有 var 的年代。
|
13
NerbraskaGuy 2023-08-30 18:31:18 +08:00
这个不算细微吧,let 和 const 被造出来基本就是为了解决 var 这个痛点的
|
14
chnwillliu 2023-09-04 11:03:33 +08:00 via Android 1
Spec 都定义好了,参见 Execution Context 的 LexicalEnvironment 和 VariableEnvironment 。他俩都是 Environment Record ,但是装的东西不一样,一个负责 let const 声明的东西,一个负责 variable statement ,hoisting 还有 with block 的差异处理都在这里规定好了。
不光这样,全局还有个特殊的 Environment Record 叫 Global Environment Records, 全局 var 和 function 会变成 global object 的属性的行为就是在这里定义的。 |
15
chnwillliu 2023-09-04 19:15:37 +08:00
仔细翻了下 Spec ,还是要纠正一下,无论 let const 还是 var ,或者是 function declaration ,class declaration ,这些 identifier 都会在 LexicalEnvironment 中记录,要查找 identifier 也只要查找 LexicalEnvironment 。而 VariableEnvironment 是专门用来管理 variable statement 的,相当于额外放一份,用来处理一些老旧 feature 比如 eval 。
let/const 和 var 的区别在于在初始进入一个 function 或者 script 的时候,只有 top level 的 let/const 会被加入到 LexicalEnvironment ,而 variable statement 声明的 identifier 和 hoistable declaration 声明的 identifier 比如 function 声明,是会在最开始就全部加入到 LexicalEnvironment 中。 实例化一个 block declaration 后,需要创建一个新的 LexicalEnvironment 给到当前的 execution context ,后续的 let/const 是加入到这个 LexicalEnvironment 中了的。比如 for ( let i=0; i<10; i++) { let j; } 这里其实创建了 11 个临时 LexicalEnvironment ,for 语句给 i 创建了一个,每次循环会创建另一个新的,放一个 j (然后销毁)。而 var 是不存在这种考量的,无论几个 for 嵌套,都会在最开始就放入顶层的 LexicalEnvironment 。 不光在开始执行一个 function 会这样处理,在新的 script element ,module 或者 worker 开始执行,都是类似处理。这个顶层 scope 或者说 LexicalEnvironment , 就是 Global Environment ,Module Environment 和 Function Environment 。 Global Environment 在每个 realm 中只有一个,在 user land 和 globalThis 是等价的,而 var 变量 和 function declaration 的 identifier 能用 globalThis 直接当属性访问也是 Global Environment Record 做的特殊处理,参见 CreateGlobalVarBinding 和 CreateGlobalFunctionBinding 。 Function Environment 在每次 call 一个 function 的时候都会创建,module 同理,在第一次 import 时创建。 一个有趣的例子,这个 early error 是如何产生的呢? ``` (function(){ { { { { var b } } let b; } } })() ``` |