let const

let 和 const 命令

1. let命令

基础使用

let声明的变量只在它所在的代码块有效。

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

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量.

另外,==for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域==。

不存在变量提升

console.log(bar); // 报错ReferenceError
let bar = 2;

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

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

使用let和const命令声明变量之前,该变量都是不可用的,从一开始就形成了封闭作用域。==凡是在声明之前就使用这些变量,就会报错.==

不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

function func(arg) {
  let arg; // 报错
}

function func(arg) {
  {
    let arg; // 不报错
  }
}

2.块级作用域

ES6 允许块级作用域的任意嵌套

  1. 外层作用域无法读取内层作用域的变量
  2. 内层作用域可以定义外层作用域的同名变量
  3. 块级作用域的出现,实际上使得立即执行(匿名)函数不再必要了。

块级作用域内声明的函数,行为类似于var声明的变量。

ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部(名提升,值留在原地)。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

根据这三条规则,==在浏览器的ES6环境中,块级作用域内声明的函数,行为类似于var声明的变量。==

function f() { console.log('I am outside!'); }
(function () {
  if (false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }
  f();
}());

/** ES5 环境 **/
function f() { console.log('I am outside!'); }
(function () {
  function f() { console.log('I am inside!'); }
  if (false) {
  }
  f();
}());

/** 浏览器的 ES6 环境 **/
function f() { console.log('I am outside!'); }
(function () {
  var f = undefined;
  if (false) {
    function f() { console.log('I am inside!'); }
  }
  f();
}());
// Uncaught TypeError: f is not a function

ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

// 报错
'use strict';
if (true)
  function f() {}

do 表达式

本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值

{
  let t = f();
  t = t * t + 1;
}
//在块级作用域以外,没有办法得到t的值,因为块级作用域不返回值,除非t是全局变量

在块级作用域之前加上do(变为do表达式),就会==返回内部最后执行的表达式的值==。

let x = do {
  let t = f();
  t * t + 1;
};
//变量x会得到整个块级作用域的返回值(t * t + 1)

3.const 命令

基本用法

  1. 一旦声明,常量的值就不能改变。

    const声明的变量不得改变值,这意味着,==const一旦声明变量,就必须立即初始化==。
    ##### 本质:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。引用类型数据结构不可变,但内部值可变。
  2. const的作用域与let命令相同:

    只在声明所在的块级作用域内有效。

  3. const命令声明的常量也是不提升,同样存在暂时性死区

    只能在声明的位置后面使用。

  4. const声明的常量,也与let一样不可重复声明

    用let声明过的变量,也不可在用const声明

如果真的想将对象冻结,应该使用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 声明变量的六种方法:
var,functionlet,const,import,class


本文来源个人对 阮一峰es6 总结,以供今后查阅。

猜你喜欢

转载自www.cnblogs.com/topyang/p/11392880.html