Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

《深入理解 ES6》let/const/var #26

Open
jiangtao opened this issue May 30, 2019 · 0 comments
Open

《深入理解 ES6》let/const/var #26

jiangtao opened this issue May 30, 2019 · 0 comments

Comments

@jiangtao
Copy link
Owner

jiangtao commented May 30, 2019

<深入理解ES6>一书中,提起 let/const 这也是平常工作用的比较多,最近需要给公司做培训. 重新复习下以往的知识点.

本文首发自 github 个人博客. 转载请注明出处. 来这里讨论

let/const

再聊 let/const之前, 让我们回顾下我们的老朋友 var, 他有什么特点或特性

var

通过下面的例子, 可以复习下, 关键字var声明带来的影响.

console.log(typeof A) // 'function'
console.log(a) // undefined
console.log(typeof a) // 'undefined'
console.log(typeof Date) // 'function'
console.log(window.Date) // function Date() {}
function A() {
    console.log(new Date())
}
var a = 10
var Date = 1000
console.log(window.Date) // 1000

由于变量提升的缘故, function 优先于 var提升且定义,此时 a只声明,未赋值,函数已声明且赋值.

同样的代码,把window改成global放在node里面运行发现结果又不一样, global.Date没有被重新赋值, 是因为在node运行环境里面, node 出于代码安全考虑, 每一个文件最终变成了由 require('module').wrapper方法包裹起来, 每一个node的 js 文件, 需要 通过exports或module.exports暴露出模块的方法和属性才能使用.

由此可见 var声明会带来以下影响

  • 变量提升 (一不小心就掉坑, 非前端开发者会很郁闷)
  • 会覆盖/污染 (当前)作用域的变量

通常的习惯可能是, 放在 top scope 的位置, 作为一个规范来约束自己或团队.

但并不是每个人都能很好的按照规范来做, 于是ES6 推出了 let/const来解决var声明的弊端

let/const

把上面的代码换成 let

console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
console.log(typeof a) // 'undefined'
console.log(typeof Date) // 'function'
console.log(window.Date) // function Date() {}

之前执行的 console.log(a) 直接报错, 阻止程序运行.

直接运行console.log(typeof a) 也一样, 而不做任何声明的时候, 会输出 'undefined'.

let a = 10
let Date = 1000
console.log(window.Date) // function Date() {}
console.log(a) // 10
console.log(Date) // 1000
console.log(window.a) // undefined

正常逻辑执行后, 并没有想象中, window.aa相等. 产生上面现象的原因是什么呢??

暂时性死区(temporal dead zone, TDZ)

let/const声明前访问其变量会造成初始化之前不能访问,这种现象叫做 TDZ.

let/const不会对 scope 域名做覆盖/污染

上述例子中, aDate声明后并没有污染 window.awindow.Date, 因此当使用的时候需要覆盖的时候使用 let/const 声明的变量, 需要手动覆盖.

循环中形成新的块级绑定

早年有一个经典的面试题, 叫做 创建10 个 div.点击输出对应的索引.

笔者在初次写 js 的时候, 写成了这种错误形式

// bad way
for(var i = 0; i < 10; i++) {
    var div = document.createElement('div')
    div.className = 'item'
    div.innerHTML = i
    div.onclick = function() {
        alert(i)
    }
    document.body.appendChild(div)
}

输出的结果也往往是 10, 需求是点击索引啊. 造成这种结果的原因是

var变量提升, 当点击的时候此时 i 是 10

因此我们常常用 IIFE(即时执行函数)

// good way
for(var i = 0; i < 10; i++) {
    var div = document.createElement('div')
    div.className = 'item'
    div.innerHTML = i
    div.onclick = (function(i) {
        return function() {
            alert(i)
        }
    })(i)
    document.body.appendChild(div)
}

那有木有更好的方案, 能不能每次 循环的时候创建一个新的 i, let具备这一特性

// better way
for (let i = 0; i < 10; i++) {
    let div = document.createElement("div");
    div.className = "item";
    div.innerHTML = i;
    div.onclick = function() {
        alert(i)
    }
    document.body.appendChild(div);
}

其他

const用来保存常量, let 在修改的使用. const 对对象处理的时候, 对象/数组属性赋值还可以修改.

关于对象的常量问题, 放到后面章节整理.

@jiangtao jiangtao changed the title 深入理解 ES6-let/const/var 《深入理解 ES6》let/const/var Jun 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant