let、const定义的变量为什么通过window获取不到
先看几个case:
let count = 10
console.log(count)
console.log(window.count)
输出:10 undefined
const length = 5
const obj = {
length: 6,
foo(bar) {
bar()
arguments[0]()
}
}
function bar() {
console.log(this.length)
}
obj.foo(bar, 2, 4)
输出: 0 3
var length = 5
const obj = {
length: 3,
foo(bar) {
bar()
arguments[0]()
}
}
function bar() {
console.log(this.length)
}
obj.foo(bar, 3)
输出: 5 2
为什么?ES5 和 ES6变量声明方式的区别导致的。首先总结下ES5 和 ES6 的变量声明方式。
- ES5 变量声明方式就两种 var、function
- ES6 有 let、const、import、class,再加上ES5 的var 和 function 总共6种
- DOM 的顶层对象是document,BOM的顶层对象是window,Node的全局对象是global
- ES5中顶层对象的属性等价于全局变量
- 在ES6中,用let、const、import、class定义的全局变量并没有作为全局对象的属性,所以通过window获取时,如果window存在和变量同名的属性,则获取的是window中该属性的原始值,否则为undefined
- 用let const在声明的时候,是创建了一个遮蔽window同名属性的全局变量,debuger一下就可以看出来用 let const 定义的变量作用域为Script对象中,和Window/Global同级。
如图:
Markdown所以
- case1首先打印10,其次是window中不存在的count属性,undefined
- case2 调用bar时,this指向window,而window中的length属性为0,所以输出0。通过arguments[0]调用,函数内的this指向argument,arguments为类数组,其length属性为实参的个数,即 3
- case3 使用var声明length,会修改window中的length属性(window的length 属性的原始值是当前窗口中frames的数量(包括IFRAMES)),所以值为0
暂时性死区(TDZ)
let const声明的变量会放在TDZ中,TDZ指的是从变量的当前的作用域开始到变量的声明之间的区域,这一段区域的变量是无法读写的。只有在执行了声明之后,才从TDZ移除。
注意点:
变量提升控制的是当前作用域或者执行环境,因此某个TDZ也只负责某个执行环境。
console.log(typeof value) // undefined
{
console.log(typeof value) // 报错 value is not defined
const value = 'rose'
}
可以看出if外访问 value 不会报错,因为 if 外 typeof value时变量还没有在TDZ中,所以是undefined。
网友评论