MeloGuo, JavaScript
Back

ES6创造出一个新东西,那必然是为了解决原有的问题。而在ES5中声明变量用的var关键字是真的有一大堆问题。

变量提升

用var声明的变量会提升(Hoisting)真的是个很恶心的事。

function foo () {
console.log(a)
var a = 1
}
foo() // undefined

明明我们是在console.log语句下方声明的a变量并且给他赋值为1,但是在声明前却可以访问到变量a,而且值为undefined

function foo () {
console.log(a)
}
foo() // ReferenceError: a is not defined

在这里,未声明变量a却还访问的结果就是会报错。

function foo () {
var a = 1
console.log(a)
}
foo() // 1

这样的声明、赋值、打印出的结果才是符合逻辑的结果。所以其实变量提升这个行为是不符合代码直观的看起来的逻辑的。

如果使用let

function foo () {
console.log(a) // ReferenceError: a is not defined
let a = 1
}

呼!在声明变量之前访问变量会报错,这样就合理多了。

没有块级作用域

在ES5中,只有全局作用域和函数作用域而没有块级作用域,也就是说:

var a = 1
{
var a = 2
}
console.log(a) // 2

明明已经在{}中重新声明了a并且赋值为2,但是在块外访问a的值却是2,在ES5中如果想把var a = 2封闭在花括号内就必须使用IIFE。

var a = 1
;(function () {
var a = 2
}())
console.log(a) // 1

通过函数作用域模拟块级作用域才能实现,但是这个语法真的很奇葩。

但是在ES6中我们有了let和const,以上的问题就全部迎刃而解了。

原来‘临时死区’不仅是不会提升,也不会通过作用域链去寻找变量。但是在let声明的块级作用域。

{
let a = 1
{
console.log(a) // ReferenceError: a is not defined
let a = 2
{
let a = 3
}
}
}

经典面试题

<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
<li>Item6</li>
</ul>
var navs = document.querySelectorAll('li')
for (var i = 0; i < navs.length; i++) {
navs[i].onclick = function () {
console.log(i)
}
}

这时候点击所有li标签都会打印出6。

解决方法1:使用IIFE

var navs = document.querySelectorAll('li')
for (var i = 0; i < navs.length; i++) {
(function (i) {
navs[i].onclick = function () {
console.log(i)
}
})(i)
}

解决方法2:使用let

var navs = document.querySelectorAll('li')
for (let i = 0; i < navs.length; i++) {
let j = i
navs[j].onclick = function () {
console.log(j)
}
}

除此之外还有一种神奇的方法

var navs = document.querySelectorAll('li')
for (let i = 0; i < navs.length; i++) {
navs[i].onclick = function () {
console.log(i)
}
} // This is a magic

但是为什么let i就可以?let i最终也会在循环结束后和var i一样变成6,那么为什么console.log(i)时候就不会都是6呢? 其实JS在这里做了很多隐藏的操作来帮助开发者在循环中方便的使用let达到这种效果。

var navs = document.querySelectorAll('li')
for (let _i = 0; _i < navs.length; _i++) {
let i = _i
navs[i].onclick = function () {
console.log(i)
}
}

其实就相当于第二种let j = i的语法糖。

有兴趣可以看看这个视频

著作权声明

本文作者 郭梓梁,首次发布于 MeloGuo Blog,转载请保留以上链接


GitHub · guoziliang199606@gmail.com · 微信
CC BY-NC 4.0 © Melo Guo.RSS