let const

2018-09-12  本文已影响0人  YJ_1101

let

块级作用域

内层变量不可能覆盖外层变量
用来计数的循环变量不会泄露为全局变量
块级作用域的出现,立即执行函数表达式(IIFE)就不再必要了。

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

// 用babel转为es5后

"use strict";

var a = [];

var _loop = function _loop(i) {
  a[i] = function () {
    console.log(i);
  };
};

for (var i = 0; i < 10; i++) {
  _loop(i);
}
a[6](); // 6

JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。 (只在for循环有用)

let i=0;i++;
console.log(i); // 1
 i=0;i++;
console.log(i); // 1
立即执行函数表达式(IIFE)
// 最常用的两种写法
(function(){ /* code */ }()); // 老道推荐写法
(function(){ /* code */ })(); // 当然这种也可以

// 括号和JS的一些操作符(如 = && || ,等)可以在函数表达式和函数声明上消除歧义
// 如下代码中,解析器已经知道一个是表达式了,于是也会把另一个默认为表达式
// 但是两者交换则会报错
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// 也可以选择一元运算符
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// 也可以这样
new function(){ /* code */ }
new function(){ /* code */ }() // 带参数
块级作用域与函数声明:

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。 ES6
引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
为了减轻因此产生的不兼容问题,ES6在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
1、允许在块级作用域内声明函数
2、函数声明类似于var 会提升到全局作用域的头部
3、函数声明还会提升到块级作用域的头部

不存在变量提升

let不会像var那样会发生‘变量提升’现象即函数及变量的声明都将被提升到函数的最顶部。。所以变量一定要在声明后使用,否则报错。

不允许重复声明

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

暂时性死区(TDZ)

如果区块存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明前使用这些变量,就会报错。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

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

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

  tmp = 123;
  console.log(tmp); // 123
}
function a() {
  console.log(i);
  function b(){
    let i = 10;
    console.log(j);
    function c(){
        let j = 20;
      console.log(i);
      console.log(j)
    }
    c()
  }
  b()
}
a()  // Uncaught ReferenceError: i is not defined

//转为es5
"use strict";

function a() {
  console.log(i);
  function b() {
    var i = 10;
    console.log(j);
    function c() {
      var j = 20;
      console.log(i);
      console.log(j);
    }
    c();
  }
  b();
}
a();
function a () {
  console.log(i);
  let i = 10;
  console.log(j);
  let j = 20;
  console.log(i);
  console.log(j);
}
//转为es5
"use strict";

function a() {
  console.log(i);
  var i = 10;
  console.log(j);
  var j = 20;
  console.log(i);
  console.log(j);
}

const

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

const声明一个只读的常量,一旦声明,常量的值就不能改变,这意味着,const一旦声明常量,就必须立即初始化,不能等到之后再赋值。因此,改变常量和只声明不赋初始值都会报错。

var i = 5;
let j = 10;
const i =6; // 报错
const j = 11; // 报错

// JS是按照代码块来进行编译和执行的,每一个script就是一个块,代码块间相互独立,但变量和方法共享
<script>
  const foo = 1  
</script>
<script>
  foo = 2
</script>
// Uncaught TypeError: Assignment to constant variable.

对于复合类型的常量,常量名不指向数据,而是指向数据所在的地址。const命令只是保证常量名指向的地址不变,并不保证该地址的数据不变,也就是说,将对象常量指向另一个地址会报错,但对象本身是可变的,可以为其添加,修改属性,因此将一个对象声明为常量必须十分小心。

const obj = {};
obj.name = “Alice”;
obj = {}; // 报错
跨模块常量

const声明的常量只能在当前代码块有效,如果想设置跨模块的常量可以采用下面的写法:

//constants.js 
export const A = 1;
export const B = 1;
export const C = 1;

//test1.js
import * as constants from './constants'

//test2.js
import {A, B} from './constants'
上一篇下一篇

猜你喜欢

热点阅读