这个问题可能显的有些小白了,只是我在看文档的时候,遇到了问题,又不知道怎么解决。
一般的文档和一些博客都说,应当避免变量污染,即,不适用var定义变量,这会导致变量成为window的属性。
然而,我今天自己写代码的时候发现,我用var aaa = 321;然后 console.log(window.aaa) => 打印321.
这就让我很奇怪了,这和博客文档说的怎么自相矛盾呢?
es6里面的let和const不会出现这种情况,抱着研究的态度,希望有能人给指出。不胜感激。
这个问题可能显的有些小白了,只是我在看文档的时候,遇到了问题,又不知道怎么解决。
一般的文档和一些博客都说,应当避免变量污染,即,不适用var定义变量,这会导致变量成为window的属性。
然而,我今天自己写代码的时候发现,我用var aaa = 321;然后 console.log(window.aaa) => 打印321.
这就让我很奇怪了,这和博客文档说的怎么自相矛盾呢?
es6里面的let和const不会出现这种情况,抱着研究的态度,希望有能人给指出。不胜感激。
在全局环境下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
定义,变量会提升至作用域顶部即全局作用域,这样导致变量成为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
8 回答4.9k 阅读✓ 已解决
6 回答3.7k 阅读✓ 已解决
5 回答3k 阅读✓ 已解决
5 回答6.5k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.5k 阅读✓ 已解决
似乎是你理解错了,正是因为你的var,导致可以用window访问var 定义的变量。
1.var 定义的是全部变量,
2.window在BOM 里有两个作用,一是作为浏览器的一个接口,二是作为Global(全局对象)
因此,在全局作用域下声明的变量方法,都会成为window 的属相和方法
你在思考下,没有矛盾的