js使用var定义的变量为什么能在window.xxx访问?

这个问题可能显的有些小白了,只是我在看文档的时候,遇到了问题,又不知道怎么解决。

一般的文档和一些博客都说,应当避免变量污染,即,不适用var定义变量,这会导致变量成为window的属性。

然而,我今天自己写代码的时候发现,我用var aaa = 321;然后 console.log(window.aaa) => 打印321.
这就让我很奇怪了,这和博客文档说的怎么自相矛盾呢?
es6里面的let和const不会出现这种情况,抱着研究的态度,希望有能人给指出。不胜感激。

阅读 7.1k
5 个回答

似乎是你理解错了,正是因为你的var,导致可以用window访问var 定义的变量。
1.var 定义的是全部变量,
2.window在BOM 里有两个作用,一是作为浏览器的一个接口,二是作为Global(全局对象)
因此,在全局作用域下声明的变量方法,都会成为window 的属相和方法

你在思考下,没有矛盾的

在全局环境下var,function声明的变量会自动成为全局对象的属性,let、const声明的变量存在词法环境中,不会挂载到全局对象上。主要原因我大致讲一下:
ECMAScript规范中定义了两种类型:一种是语言类型,比如Object、String、Number等。还有一种是规范类型,你不能用javascript语言具体的访问到,只存在语言内部。规范类型中有一种叫词法环境也就是常说的词法作用域。每一个词法环境都有自己的环境记录。全局环境有对应的全局环境记录,全局环境记录是对象环境记录和声明性环境记录的一个组合。每个对象环境记录绑定了一个对象,全局环境下绑定的就是全局对象,浏览器下是window,node下是global。全局环境下的对象环境记录中指出了绑定的对象中包含内建的绑定,像Object、Array、evel、Date等属性,还有FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration,和VariableDeclaration的绑定,也就是var、function声明的变量,所以在全局环境下var,function声明的变量会成为全局对象的属性,上面说的4种声明外,所有其他的声明都属于声明性环境记录,也就是说let、const声明的变量属于声明性环境记录,此外还包括class声明的变量等。所以let和const声明的变量你是不能用window.xxx访问的。
具体你可以看https://segmentfault.com/a/11... 这篇文章

var aaa = 321 === this.aaa=321

你定义的是全局变量 this===window

window.aaa===this.aaa

打印的结果就是博客文档所说的内容,使用var定义,变量会提升至作用域顶部即全局作用域,这样导致变量成为window的属性,那么访问window.aaa当然可以得到321
使用ES6中的let和const则不会出现这种情况,因为它们可以把变量的作用域限制在当前代码块中即局部作用域,并且声明的变量不会被提升,所以不会出现window.aaa的打印结果为321。
另外就变量提升而言,下面有一个很明显的栗子:

// 使用var声明
console.log(aaa)
var aaa = 321    // undefined

// 使用let声明
console.log(aaa)    // Uncaught ReferenceError(报错)
let aaa = 321

文档说的没毛病,console.log(window.aaa) 结果是321,不就是说明aaa作为window的属性了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏