var (函数作用域):可以重新赋值,重新定义 let (块级作用域): 不能重新声明,可以修改 const (块级作用域):不能重新声明,不能修改–常量
<script> // var 是全局变量, for(var i = 0; i < 10 ; i++ ){ console.log(i);//因为是全局变量,在执行之后i= 10 } for(let i = 0; i < 10 ; i++){ console.log(i); setTimeout(function(){ console.log(i);//let 是块级,i=0,1,2,3...9 },1000) } </script>var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。let没有变量提升
console.log(fo);//输出undefined var fo = 3; console.log(ba);//报错ReferenceError let ba = 1;ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。 总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区“简称TED
if (true) { // TDZ开始 tmp = 'abc'; // ReferenceError console.log(tmp); // ReferenceError //在没有声明变量之前tmp都是错误的 let tmp; // TDZ结束 console.log(tmp); // undefined tmp = 123; console.log(tmp); // 123 }let不允许在相同作用域内,重复声明同一个变量。
function fun1(){ let a = 8; let a = 2; //会报错 }不能在函数内部重新声明参数
function fun(arr){ let arr; } fun();//会报错 function fun(arr){ { let arr; } } fun();//不会报错一个 { } 就是一个块级作用域 在块级作用域下var声明的变量依然是全局的 在块级作用域下let,const声明变量是私有的
{ let b = 1; var a = 0; } console.log(a);//0 console.log(b);//b is not defined如果想表示一个对象,需要用变量接收,否则会被当成块级作用域。
这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let [foo, [[bar], baz]] = [1, [[2], 3]]; foo // 1 bar // 2 baz // 3 let [ , , third] = ["foo", "bar", "baz"]; third // "baz" let [x, , y] = [1, 2, 3]; x // 1 y // 3 let [a, [b], d] = [1, [2, 3], 4]; a // 1 b // 2 d // 4如果解构不成功,变量的值就等于undefined。
let arr = [1, 2, 3,4]; let [a, b, c, d, e] = arr; console.log(a, b, c, d, e);//1,2,3,4,undefined省略赋值
let [,,b]=[1,2,3]; consloe.log(b);//3不定参数赋值
let [x1,x2,...x3]=[1,2,3,4,5]; console.log(x3);//[3,4,5]对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
变量名和属性名一致
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; foo // "aaa" bar // "bbb"变量名和属性名不一致
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" foo // error: foo is not defined嵌套
let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p, p: [x, { y }] } = obj; x // "Hello" y // "World" p // ["Hello", {y: "World"}] let obj = {}; let arr = []; ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });//不能对块级作用域直接赋值,所以加个括号 obj // {prop:123} arr // [true]字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello'; a // "h" b // "e" c // "l" d // "l" e // "o"类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length : len} = 'hello'; len // 5解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
let {toString: s} = 123; s === Number.prototype.toString // true let {toString: s} = true; s === Boolean.prototype.toString // true只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
let { prop: x } = undefined; // TypeError let { prop: y } = null; // TypeError