《es6 标准入门》知识整理(1) - let 和 const

let 基本用法

es6 的 let 所声明的变量,只在 let 命令所在的代码块内有效。for循环的计数器,就很适合用let命令:javascript

for (let i=0; i< 10; i++) {
    //..
    }
    console.log(i) // ReferenceError: i is not defined

由于计数器 i 只在 for 循环体内有效,在循环体外引用就会报错。java

for循环有一个特别之处,设置循环变量的那部分是一个父做用域,而循环体内是一个单独的子做用域。es6

for(let i =0; i< 3; i++) {
    	let i = 'abc';
    	console.log(i);
    }
    // abc
    // abc
    // abc

上面代码输出了 3 次 abc, 这代表函数内部的变量 i 和循环变量 i 不在同一个做用域,有各自独立的做用域;编程

特性1- 没有变量提高和暂时性死区

咱们知道, var 声明的变量会存在变量提高现象,可是 let 不会,let 声明的变量必定在声明后使用。不然报错。好比:数组

// es5
    console.log(i); // undefined
    var i = 10;
	// es6
    console.log(j);// ReferenceError
    let j = 10;

只要块级做用域内存在 let 和 const 命令,它所声明的变量就“绑定”在这个区域,再也不受外部的影响。凡是在声明以前就使用这些变量,就会报错,这种称为“暂时性死区(TDZ)“;浏览器

TDZ的本质是只要进入当前做用域,所要使用的变量就已经存在了,可是不可获取,只有等到声明变量的那一行代码出现,才能够获取和使用该变量。数据结构

let i = 5;
    if(true) {
    	console.log(i);// Uncaught ReferenceError: i is not defined
    	let i=10;
    }

虽然全局做用域内有 i 这个变量,可是局部做用域里用 let 声明了一个同名变量,因此最后 i 就被绑定到局部做用域里,它未声明就使用,因此会报错。ide

这样的设计是为了让你们养成良好的编程习惯,变量必定要在声明以后使用。不然就报错。函数

特性2 - 不容许重复声明

let不容许在相同做用域内,重复声明同一个变量;es5

function fuc() {
      let a= 10;
      let a = 1;
    }// 报错
    function func () {
    	let a= 10;
    	{
    	  let a = 1;
    	}
    }// 不报错,不属于同一做用域

为何须要块级做用域?

es5 只有全局做用域和函数做用域,没有块级做用域,这产生不少不合理的场景。

场景1,内层变量可能会覆盖外层变量

var tmp = new Date();
    function f() {
    	console.log(tmp);
    	if(false) {
    	  var tmp = 'hello world'
    	}
    }
    f()// undefined;

if 代码块的外部使用外层的 tmp 变量,内部使用内层的 tmp 变量,可是。函数 f 执行后,输出为undefined;缘由在于变量提高致使的 tmp 变量覆盖了外层的 tmp 变量;

场景2, 用来计数的循环变量泄露为全局变量

var  s = 'hello';
    for(var i = 0; i < s.length; i++) {
    	console.log(i);
    }
    conole.log(i);

这里,i 只是用来控制循环, 可是它没有消失,泄露成了全局变量。

块级做用域中的函数声明

函数能不能在块级做用域中声明?

es5 规定,函数只能在顶层做用域和函数做用域之中声明,不能在块级做用域中声明。

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

这串代码在 es5 中运行,照规定来讲是非法的,可是为了兼容,仍是支持在块级做用域中声明函数,所以会获得’inside'; 由于在 if 中声明的函数会被提高到函数头部,实际执行的代码为:

function f() { console.log('outside');}
    (function () {
    	function f() {console.log('inside');}
    	if (false) {
    	}
    	f();
    }());

在 es6中 执行会怎么样?会报错

es6规定,函数能够在块级做用域内声明。函数声明的语句相似于let,在块级做用域以外不能够引用。

  • 容许在块级做用域内声明函数
  • 函数声明相似于 var, 即会提高到全局做用域或函数做用域的头部
  • 函数声明还会提高到所在的块级做用域的头部
  • 只在使用大括号的状况下成立

上面的代码在符合es6的浏览器中,实际运行的是:

function f() { console.log('outside');}
    (function () {
    	var f = undefined;
    	if (false) {
    	  function f() {console.log('inside');}
    	}
    	f();
    }());

因此咱们应该避免在块级做用域内声明函数,若是须要,函数声明应该写成函数表达式,如

{
    	let a='haha';
    	let f = function () {
    	return a;
    	}
    }

块级做用于域的返回值

块级做用域不会返回值,咱们能够将块级做用域变为表达式。在 {} 以前加上do, 而后就会返回内部最后执行的表达式的值。不过如今这只是个提案,如今这样写 do是浏览器没法解析的。

let x = do {
    	let t = f();
    	t*t+1;
    }

const 的本质

const定义的是常量,它不是指变量的值不能改动,而是变量指向的那个内存地址不能改动。对于简单类型的数据,值就保存在变量指向的那个内存地址,所以等同于常量,而符合类型的数据(数组和对象),变量指向的内存地址,保存的只是一个指针, const只能保证这个指针式固定的,而它指向的数据结构是不可控的。

总结

let 和 const 的特性有:

  • 只在本身的块做用域内有效;块做用域指的是{}。
  • 存在”暂时性死区“(TDZ),
  • 只能在声明以后使用
  • 不存在变量提高;
相关文章
相关标签/搜索