最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 学习JavaScript红宝书(四)——变量声明之var,let,const

    正文概述 掘金(程序员阿来)   2021-03-19   617

    变量声明

    ECMAScript 中的变量是松散类型的,意思是变量可以用于保存任何类型的数据。每个变量只不过是一个用于保存任意值的命名占位符。

    JavaScript有三个声明变量的关键字:var, const, let。其中 const, let 只能在 ECMAScript 及更晚的版本中使用。

    var

    var message;
    

    这样就定义了一个名为 message 的变量,可以用它保存任何类型的值。

    ECMAScript 实现变量初始化,因此可以同时定义变量并设置它的值。

    var message = "hi";
    

    定义好之后,不仅可以改变值,甚至可以改变它的类型。

    var message = "hi";
    message = 100;
    

    这样虽然合法,但不推荐,也很少看到程序员会这样做。

    对于多个变量可以一次性声明:

    var message = "hi",
      found = "false",
      age = 29;
    

    因为 ECMAScript 是松散类型的,所以使用不同数据类型初始化也可以用一条语句。

    var 可以重复声明同一个变量:

    var age = 16;
    var age = 26;
    var age = 36;
    

    var 声明作用域

    使用 var 声明的变量会成为包含它的函数的局部变量。比如,在一个函数内部 var 一个变量,这个变量将在函数退出时被销毁。

    function test() {
      var message = "hi";
    }
    test();
    console.log(message);
    

    因为 message 在函数调用完后已经被销毁,所以上面的代码在试图打印的时候就会报错。这种时候可以省略 var,将其声明为全局变量。

    function test() {
      message = "hi";
    }
    test();
    console.log(message);
    

    var 变量声明提升

    console.log(age);
    var age = 26;
    function test() {
      console.log(age);
      var age = 30;
    }
    

    像这样的代码是不会报错的,并不是解析器没有按顺序。而是 var 声明会被提升到顶部,变成

    var age;
    console.log(age);
    age = 26;
    function test() {
      var age;
      console.log(age);
      var age = 30;
    }
    

    这就是变量声明提升机制(hoist)。

    let

    let 声明的是块作用域,而 var 声明的是函数作用域。这是他们两个最明显的区别。

    if (true) {
      var name = "Matt";
      console.log(name); // Matt
    }
    console.log(name); // Matt
    
    if (true) {
      let name = "Matt";
      console.log(name); // Matt
    }
    console.log(name); // undefined
    

    用 let 声明的变量只能在 if 块内使用。它的作用域范围比 var 小,所以自然也不能在函数外被使用。

    并且 let 也不允许反复声明同一个变量,这个特性在有些时候被称为声明屏蔽:

    let age;
    let age;
    

    会报 SyntaxError,标识符已经声明过了。

    而正因为 let 声明的作用域在块内,所以下面这样嵌套使用相同的标识符是合法的。

    let age = 30;
    if (true) {
      let age = 26;
    }
    

    let 没有变量声明提升,只有暂时性死区

    不能先使用再声明,下面这样报错

    console.log(age);
    let age = 27;
    

    在 let 声明之前的执行瞬间被称为暂时性死区(temporal dead zone),会抛出 ReferenceError 这个错误。

    let 全局声明的变量不会成为window 对象的属性

    这与 var 不同:

    var name = "Matt";
    console.log(window.name); // Matt
    
    let age = 26;
    console.log(window.age); // undefined
    

    let 不能用条件声明

    if (typeof name === "undefined") {
      let name;
    }
    

    像这样有条件的情况下声明的 let 变量依旧只能在块内使用,不能在有条件的情况下声明出全局的 let 变量。

    for 循环中的 let

    这推荐使用 let 而不用 var 的一个重要原因。

    使用 var 声明的迭代变量会渗透到循环体外部:

    for (var i = 0; i < 5; i++) {
      // 循环逻辑
    }
    console.log(i); // 5
    

    但是使用 let 就不会有这个问题:

    for (let i = 0; i < 5; i++) {
      // 循环逻辑
    }
    console.log(i); // ReferenceError: i没有定义
    

    使用 var 的时候还会有一个问题,还经常被拿来当面试题:

    for (var i = 0; i < 5; i++) {
      setTimeout(() => console.log(i), 0);
    }
    

    预想的是输出:0 1 2 3 4

    但实际输出的却是:5 5 5 5 5

    之所以这样是因为:首先 setTimeout 是一个超时逻辑,它会在循环退出后再开始执行,而循环退出时,迭代变量保存的是导致循环退出的值:5。所有的 i 都是同一个变量,因而输出的都是同一个最终值。 对此其实有一个解决方法是使用立即执行的函数表达式(IIFE)来捕获每次迭代时 i 的值。

    for (var i = 0; i < 5; i++) {
      (function (i) {
        setTimeout(() => console.log(i), 0);
      })(i);
    }
    

    或者直接let 声明迭代变量。这样JavaScript 会在后台为每个迭代循环声明一个新的迭代变量。所以它会有 5 个 i,值分别是 0、1、2、3、4,每个 setTimeout 引用的都是不同的变量实例。

    for (let i = 0; i < 5; i++) {
      setTimeout(() => console.log(i), 0);
    }
    

    这种每次迭代声明一个独立变量实例的行为适用于所有风格的 for 循环,包括 for-in 和 for-of 循环。

    const

    const 与 let 基本相同,唯一重要区别是

    它声明变量时必须同时初始化变量,且声明后的值不能再修改。

    const 也不允许重复声明。

    const 声明的作用域也是块。

    但是 const 只限制它指向的变量。也就是说,如果 const 声明了一个对象,那么修改对象内的属性是合法的。

    const person = {};
    person.name = "Matt";
    

    const 一般不用来声明迭代变量,因为它不会被修改。但是在 for-in 和 for-of 中却是有意义的:

    for (const i = 0; i < 5; i++) {} // TypeError: 给常量赋值
    
    let i = 0;
    for (const j = 0; i < 5; i++) {
      console.log(j);
    }
    // 0 0 0 0 0
    
    for (const key in { a: 1, b: 2 }) {
      console.log(key);
    }
    // a b
    
    for (const value of [1, 2, 3, 4, 5]) {
      console.log(value);
    }
    // 1 2 3 4 5
    

    推荐的声明风格

    ECMAScript6 增加 let 和 const 支持更精确地声明作用域和语义。

    天下苦 var 久矣, 是时候抛弃它了。

    1. 不使用 var

    有了 let 和 const 之后,var 已经不再被需要。Eslint 代码规范,也要求开发者不要使用 var,并添加了将 var 自动转变成 let 或 const 的功能。

    2. const 优先,let 次之

    const 声明的变量在浏览器运行时强制保持不变,方便静态代码分析工具提前发现不合法的赋值操作。对于开发者,也可以更容易发现意外赋值导致的非预期行为。


    起源地下载网 » 学习JavaScript红宝书(四)——变量声明之var,let,const

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元