let和const命令

let命令

1. 基本用法

let和var的基本区别是作用域的区别,let可以设置块级作用域,特别适合for循环,在块级作用域之外访问则出错。下面是一个对比:
使用var:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); //  10

使用let:

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6]();   // 6

对比两个结果,变量i是var声明的时候,在全局范围内有效,因此全局只有一个变量i,变量i是let声明的时候,只在本次循环内有效,因此每次循环都会生成一个变量i。这里有一个问题,既然每次循环都重新声明一个变量i,那它怎么知道上次循环的值,从而计算本次的i值呢?javascript引擎内部会记住上一次的值,下次初始化本轮i时,会在上一轮的基础上进行计算。

2. 暂时性死区

ES6和ES5的一个重要区别,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。目的是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。

3.ES6的块级作用域

各层级代码块之间不受影响。

function f1(){
            let n = 5;
            if(true){
                let n = 10;
            }
            console.log(n);  // 5
        }

        f1();

块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。

// IIFE 写法
(function () {
  var tmp = ...;
  ...
}());

// 块级作用域写法
{
  let tmp = ...;
  ...
}

3.块级作用域与函数声明

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是浏览器没有遵守这个约定,在块级作用域之中声明函数,不会报错。
但是在ES6中,明确允许在块级作用域之中声明函数。函数声明语句的行为类似于let,在块级作用域之外不可引用。
ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

const命令

const和let的基本用法是一样的,只在声明所在的块级作用域有效,同样存在暂时性死区。

本质:
const保证的,不是变量的值不能改动,而是变量指向的内存地址所保存的数据不能改动。对于简单的数据类型,比如数值、字符串和布尔值,值就保存在变量指向的内存地址,等同于常量,对于复合类型的数据,比如对象和数组,变量指向的地址实际上是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。

const a = [];
a.push('Hello'); // 可执行
a.length = 0;    // 可执行
a = ['Dave'];    // 报错

上面代码中,常量a是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错。

如果真的想将对象冻结,应该使用Object.freeze方法。

const foo = Object.freeze({});

// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

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

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

ES6 声明变量的六种方法:
ES5中的var和function,加上ES6新添加的let、const、import、class命令。

顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。
ES6中,为了保持与ES5的兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

你可能感兴趣的:(前端,ECMAScript6)