zoukankan      html  css  js  c++  java
  • 1 let和const

    • let命令

    1)let声明的变量只在let命令所在的代码块内有效,如:
     
    1 {
    2   let a = 10;
    3   var b = 1;}
    4 
    5 a // ReferenceError: a is not defined.
    6 b // 1

     

    对于for循环计数器,如果使用var声明,
     
     1 var a = [];for (var i = 0; i < 10; i++) {
     2   a[i] = function () {
     3     console.log(i);
     4   };}
     5 a[6](); // 10
     6 a[6]的结果是最后一轮的i值,而使用let时a[6]的值则为6
     7 var a = [];for (let i = 0; i < 10; i++) {
     8   a[i] = function () {
     9     console.log(i);
    10   };}
    11 a[6](); // 6

     

    2)let不像var那样会发生“变量提升”现象,所以,变量一点要在声明之后使用。
    3)暂时性死区
    只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不在受外部的影响。
    在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。
     
    ES6规定暂时性死区和不存在变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
     
    4)不允许重复声明
    let不允许在相同作用域内重复声明同一个变量。
     
    // 报错
    function () {
      let a = 10;
      var a = 1;}
    // 报错
    function () {
      let a = 10;
      let a = 1;}

     

    • 块级作用域

    ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
    第一种场景,内层变量可能会覆盖外层变量。
     
    1 var tmp = new Date();
    2 
    3 function f() {
    4   console.log(tmp);
    5   if (false) {
    6     var tmp = "hello world";
    7   }}
    8 
    9 f(); // undefined
    上面代码中,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
    第二种场景,用来计数的循环变量泄漏为全局变量。
     
    1 var s = 'hello';
    2 
    3 for (var i = 0; i < s.length; i++) {
    4   console.log(s[i]);}
    5 
    6 console.log(i); // 5

     

    上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
    而let实际上为JavaScript新增了块级作用域。
     
    1 function f1() {
    2   let n = 5;
    3   if (true) {
    4     let n = 10;
    5   }
    6   console.log(n); // 5
    7 }
    上面的函数有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var定义变量n,最后输出的值就是10。
    • ES6允许块级作用域的任意嵌套
    • 内层作用域可以定义外层作用域的同名变量
    • 块级作用域的出现,实际上使得立即执行匿名函数(IIFE)不再必要了。
    1 // IIFE写法
    2 (function () {
    3   var tmp = ...;
    4   ...}());
    5 // 块级作用域写法
    6 {
    7   let tmp = ...;
    8   ...}
    • 块级作用域与函数声明

    ES6引入了块级作用域,明确允许在块级作
    用域之中声明函数,并且在块级作用域中函数声明的语句类似于let,在块级作用域之外不可引用。
    ES6的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。
     
    1 // 不报错
    2 'use strict';if (true) {
    3   function f() {}}
    4 // 报错
    5 'use strict';if (true)
    6   function f() {}
    • const命令

    const声明一个只读的常量。一旦声明,常量值就不能改变。这样意味着,const一旦声明变量就必须立即初始化,不能留到以后赋值。
    1 const foo;
    2 // SyntaxError: Missing initializer in const declaration

    const的作用域与let命令相同,只在声明所在的块级作用域内有效。

    const声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
    const也不可重复声明。
    对于符合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令指示保证变量名指向的地址不变,并不保证改地址的数据不变,所以将一个对象声明为常量必须非常小心。
     1 const foo = {};
     2 foo.prop = 123;
     3 
     4 foo.prop
     5 // 123
     6 
     7 foo = {}; // TypeError: "foo" is read-only
     8 如果想将对象冻结,应该使用Object.freeze方法
     9  
    10 const foo = Object.freeze({});
    11 // 常规模式时,下面一行不起作用;
    12 // 严格模式时,该行会报错
    13 foo.prop = 123;

    除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。

     
    1 var constantize = (obj) => {
    2   Object.freeze(obj);
    3   Object.keys(obj).forEach( (key, value) => {
    4   if ( typeof obj[key] === 'object' ) {
    5   constantize( obj[key] );
    6   }
    7   });};

     

    ES6一共有6种声明变量的方法:var function let const import class
     
    • 全局对象的属性

    全局对象是最顶层的对象,在浏览器环境中是指window对象,在Node.js中是global对象。在ES5中全局对象的属性与全局变量是等价的。
    在ES6中,为了保持兼容性,var命令和function命令声明的全局变量依旧是全局对象的属性;另一方面:let和const以及class声明的全局变量不属于全局对象的属性。从ES6开始,全局变量将逐步与全局对象的属性脱钩。
     
    1 var a = 1;
    2 // 如果在Node的REPL环境,可以写成global.a
    3 // 或者采用通用方法,写成this.a
    4 window.a // 1
    5 let b = 1;
    6 window.b // undefined
    上面代码中,全局变量a由var命令声明,所以它是全局对象的属性;全局变量b由let命令声明,所以它不是全局对象的属性,返回undefined。
     
  • 相关阅读:
    (Java) LeetCode 44. Wildcard Matching —— 通配符匹配
    (Java) LeetCode 30. Substring with Concatenation of All Words —— 与所有单词相关联的字串
    (Java) LeetCode 515. Find Largest Value in Each Tree Row —— 在每个树行中找最大值
    (Java) LeetCode 433. Minimum Genetic Mutation —— 最小基因变化
    (Java) LeetCode 413. Arithmetic Slices —— 等差数列划分
    (Java) LeetCode 289. Game of Life —— 生命游戏
    (Java) LeetCode 337. House Robber III —— 打家劫舍 III
    (Java) LeetCode 213. House Robber II —— 打家劫舍 II
    (Java) LeetCode 198. House Robber —— 打家劫舍
    (Java) LeetCode 152. Maximum Product Subarray —— 乘积最大子序列
  • 原文地址:https://www.cnblogs.com/wjlog/p/5693018.html
Copyright © 2011-2022 走看看