let和const命令

let 命令

let只在声明所在的块级作用域内有效,需要先申明后使用

{
  let a = 10;
  var b = a;
}
a // ReferenceError: a is not defined
b // 1
var a = [];
for (var i=0;i<10;i++>) {
  a[i] = function () {
    console.log(i);
  }
}
a[6](); // 10

原因:变量i是var命令声明的,在全局范围内都有效,全局只有一个变量i,每次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数console.log(i),里面的i指向的是全局i(也就是同一个i,即最后一轮的i的值,也就是10),修改方法var改成let或者将内层函数变成块级作用域,外层i作为变量值传给块级作用域的函数。

const 命令

const声明一个只读的常量,一旦声明变量,就必须立即初始化,不能留到以后赋值。

const foo;
// SyntaxError: Missing initializer in const declaration

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单数据类型(数值、字符、布尔值),值保存在内存地址里,对于复杂数据类型(数组、对象),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,对于值是否改变不可以保证。

<!-- 对象 -->
const foo = {}
foo.name = 'a'; // 正确
foo = {} // 错误

<!-- 数组 -->
const arr = []
arr.push('a'); // 正确
arr.length = 0; // 可执行
arr = ['a']; // 报错

如果想让定义的对象或数组冻结,可以使用Object.freeze方法,当使用Object.freeze方法冻结对象或数组时,添加新属性不起作用,严格模式下会报错。

const foo = Object.freeze({});
// 常规模式时,下面一行不起作用
// 严格模式时,报错
foo.name = 'a';

const arr = Object.freeze([]);
// 常规模式时,下面一行不起作用
// 严格模式时,报错
arr[0] = 'a';

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

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

const foo = {
  name: 'a'
}
foo.age = 20; // 正确
foo.name = 'Lily'; // 正确
constantize(foo);
foo.age = 20; // 报错
(0)

相关推荐