一、块级绑定

ES2015

一、块级绑定

1、let、const和块级作用域

var 变量提升(hoisting )

  使用var关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于所在函数的顶部(如果声明不在任意函数内,则视为在全局作用域的顶部)。

    function getValue(condition) {
        //value声明被提升到此处
        if (condition) {
            var value = "blue";
            // 其他代码
            return value;
        } else {
            // value 在此处可访问,值为 undefined
            return null;
        }
        // value 在此处可访问,值为 undefined
    }

let声明

  let 声明的语法与 var 的语法一致,但会将变量的作用域限制在当前代码块中。

    function getValue(condition) {
        if (condition) {
            let value = "blue";
            // 其他代码
            return value;
        } else {
            // value 在此处不可用
            return null;
        }
        // value 在此处不可用
    }

  禁止重复声明
  如果一个标识符已经在代码块内部被定义,那么在此代码块内使用同一个标识符进行 let 声明就会导致抛出错误。

    var count = 30;
    let count = 40;// 语法错误
    if (condition) {
        let count = 40;// 不会抛出错误
        // 其他代码
    }

常量声明

  所有的const变量都需要在声明时进行初始化,常量声明与 let 声明一样,都是块级声明。

    const maxItems = 30;// 有效的常量  
    const name;// 语法错误:未进行初始化

  常量如果是一个对象,它所包含的值是可以被修改的。

    const person = {
        name: "Nicholas"
    };
    person.name = "Greg";// 工作正常
    person = {// 抛出错误
        name: "Greg"
    };

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

    console.log(typeof value); // "undefined"
    if (condition) {
        console.log(typeof value); // 引用错误
        let value = "blue";
    }

循环内的函数

    var funcs = [];
    for (var i = 0; i < 10; i++) {
        funcs.push(function() { console.log(i); });
    }
    funcs.forEach(function(func) {
        func(); // 输出数值 "10" 十次
    });

  强制修正

    var funcs = [];
    for (var i = 0; i < 10; i++) {
        funcs.push((function(value) {
            return function() {
                console.log(value);
            }
        }(i)));
    }
    funcs.forEach(function(func) {
        func(); // 从 0 到 9 依次输出
    });

循环内的 let 声明

  这种方式在 for-in和 for-of 循环中同样适用(每次循环都创建一个副本,const同理)

    var funcs = [];
    for (let i = 0; i < 10; i++) {
        funcs.push(function() {
            console.log(i);
        });
    }
    funcs.forEach(function(func) {
        func(); // 从 0 到 9 依次输出
    })

  需要重点了解的是: let 声明在循环内部的行为是在规范中特别定义的,而与不提升变量声明的特征没有必然联系。事实上,在早期 let 的实现中并没有这种行为,它是后来才添加的。

循环内的 const 声明

    var funcs = [];
    for (const i = 0; i < 10; i++) {//循环第二次抛出错误
        funcs.push(function() {
            console.log(i);
        });
    }
    funcs.forEach(function(func) {
        func();
    })
    var funcs = [],
        object = {
            a: true,
            b: true,
            c: true
        };
    for (const key in object) { // 不会导致错误
        funcs.push(function() {//循环内部,key不能被修改
            console.log(key);
        });
    }
    funcs.forEach(function(func) {
        func(); // 依次输出 "a"、 "b"、 "c"
    });

  const 和 let 情况相同,但是const在for循环中是不能被改变的,所有会抛出错误,for-in for-of是创建副本不是改变const,所以不会抛出错误,但是在循环内部,同样是不能被改变的

全局块级绑定

  var 声明全局变量会覆盖全局属性

    var RegExp = "Hello!";
    console.log(window.RegExp); // "Hello!"

  const let不会覆盖全局属性

    // 在浏览器中
    let RegExp = "Hello!";
    console.log(RegExp); // "Hello!"
    console.log(window.RegExp === RegExp); // false

  若想让代码能从全局对象中被访问,你仍然需要使用 var 。在浏览器中跨越帧或窗口去访问代码时,这种做法非常普遍。

总结

  let 与 const 块级绑定将词法作用域引入了 JS 。这两种声明方式都不会进行提升,并且只会在声明它们的代码块内部存在。由于变量能够在必要位置被准确声明,其表现更加接近其他语言,并且能减少无心错误的产生。作为一个副作用,你不能在变量声明位置之前访问它们,即便使用的是 typeof 这样的安全运算符。由于块级绑定存在暂时性死区( TDZ ),试图在声明位置之前访问它就会导致错误。
  let 与 const 的表现在很多情况下都相似于 var ,然而在循环中就不是这样。在 for-in与 for-of 循环中, let 与 const 都能在每一次迭代时创建一个新的绑定,这意味着在循环体内创建的函数可以使用当前迭代所绑定的循环变量值(而不是像使用 var 那样,统一使用循环结束时的变量值)。这一点在 for 循环中使用 let 声明时也成立,不过在 for 循环中使用 const 声明则会导致错误。
  块级绑定当前的最佳实践就是:在默认情况下使用 const ,而只在你知道变量值需要被更改的情况下才使用 let 。这在代码中能确保基本层次的不可变性,有助于防止某些类型的错误。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容

  • ES6学习笔记 1.块级绑定 在类C语言中变量是在声明的地方创建。在JS中变量实际创建位置取决于你如何声明它。es...
    小线亮亮阅读 179评论 0 0
  • 前言:块绑定 在传统意义上,变量声明工作的方式在Js一直是棘手的编程部分,在大多数基于C语言的编程语言中,变量(或...
    拾谷阅读 192评论 0 0
  • 原创文章&经验总结&从校招到A厂一路阳光一路沧桑 详情请戳www.codercc.com 主要知识点有:var变量...
    你听___阅读 649评论 0 1
  • 1. EcmaScript 5作用域 EcmaScript5的作用域有全局作用域(global scope)与函数...
    Coder_不易阅读 1,782评论 0 1
  • 上面这两个有用如此小清新范儿的名字的ID,是我在微博上常关注的两个妹子。 此前,我从未想过将两个毫无干系的妹子放在...
    家有四宝阅读 2,527评论 1 0