let、const定义的变量为什么通过window获取不到

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 的变量声明方式。

  1. ES5 变量声明方式就两种 var、function
  2. ES6 有 let、const、import、class,再加上ES5 的var 和 function 总共6种
  3. DOM 的顶层对象是document,BOM的顶层对象是window,Node的全局对象是global
  4. ES5中顶层对象的属性等价于全局变量
  5. 在ES6中,用let、const、import、class定义的全局变量并没有作为全局对象的属性,所以通过window获取时,如果window存在和变量同名的属性,则获取的是window中该属性的原始值,否则为undefined
  6. 用let const在声明的时候,是创建了一个遮蔽window同名属性的全局变量,debuger一下就可以看出来用 let const 定义的变量作用域为Script对象中,和Window/Global同级。

如图:

Markdown

所以

  1. case1首先打印10,其次是window中不存在的count属性,undefined
  2. case2 调用bar时,this指向window,而window中的length属性为0,所以输出0。通过arguments[0]调用,函数内的this指向argument,arguments为类数组,其length属性为实参的个数,即 3
  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。

你可能感兴趣的:(let、const定义的变量为什么通过window获取不到)