深入原理:块级作用域、解构赋值

块级作用域:

特点: 不存在变量声明提升;作用域仅在所在的{}之内(称为暂时性死区);不允许重复声明;

  1. let
let i= 10;
for(let i = 0;i<10;i++){
	let i= 20;
}
//  本段代码并不会报错(不允许重复声明错误),因为是三个层级的i,注意for循环的()与{}属于两个层级
//  即:
let i = 10
{
	let i =0;
	{
		let i = 20;
	}
}
  1. const
    const定义的变量是一个常量,不能改变;
    如果const定义的是一个对象,可以改变该对象的值,但不能改变地址;
    const实质是定义的是一个变量占用的地址不能改变,但地址内的数据可以改变;
    如:
const A= 0;
A = 1;//会报错
const obj = {};
obj.a = 10;
obj = {b:10}; //此时会报错,因为地址被改变;

解构赋值(实质是模式匹配)

  1. 数组的解构赋值:
let [a,b,c] = [1,2,3];   //基本形式写法
//  以上相当于:
let a =1;
let b =2;
let c = 3;
//  并且可以进行复杂的嵌套,甚至支持默认值的写法:let [a= 10] = [20];

解构失败:let [a,b] = [1]; // 此时b为undefined
不完全解构:let [a] = [1,2];
实质上,当右边的值绝对(===)等于undefined的时,才会用左边的默认值;并且是一种惰性赋值(不用不加载);
例:

let [x = 1,y = x] = [];       //   x=1  y=1
let [x = 1,y = x] = [2];   	  //   x=2  y=2
let [x = 1,y = x] = [2,4];    //   x=2  y=4
let [x = y,y = 1] = [];       //   报错,使用了let,先使用后声明
let [x = y,y = 1] = [2];      //   x=2  y=1
  1. 对象的解构赋值:
let {bar,foo} = { b:123, f:456};   //  简写形式  

注意:以下两种写法输出

let {bar,foo} = { bar:123, foo:456}; console.log(bar,foo);     // 123 456
let {bar,foo} = { foo:456, bar:123};   console.log(bar,foo);   // 123 456
//说明此时匹配到的值是无序的   (对象存储的值是键值对的形式,本身就是无序的)
let {bar,foo} = { b:123, f:456};   console.log(bar,foo);       // undefined undefined
let {foo:bar} = {foo:123};console.log(bar);console.log(foo);   //123  报错   

看到这里,是不是突然发现刚刚得到的规律好像并不适用于此行???

实质上: 上面的基本形式只是一种简写,完整形式写法为:let {bar:bar,foo:foo} = {bar:123,foo:456};:前面的bar/foo代表的是一种模式(不具有意义),是根据模式进行匹配,把值给后面的即:

let {bar:ba,foo:fo} = {ba:123,fo:456};        console.log(bar,foo,ba,fo);  //报错(not def)、报错(not def)、undef、undef 
let {bar:ba,foo:fo} = {bar:123,foo:456};      console.log(bar,foo,ba,fo);  //报错(not def)、报错(not def)、123、456

当bar与ba都写为bar时,可以是最上面的简写形式;

在举一个嵌套例子:

let obj = {
	p : [
		"hello",
		{y : 123}
	]
}
let {p:[x,{y:aa}]} = obj;
console.log(x,aa);             //hello  123
console.log(p,y);              //报错(not def)、报错(not def)

那么,怎么把obj里的p拿出来呢?我们在愿来obj的基础上执行:let {p,p:[x,{y:aa}]} = obj;console(p,x); //["hello",{y:123}] , hello,这说明被可以解构多次!!
并且同样支持默认赋值;
3. 解构赋值扩展

let [a,b] = 12;                                  //报错(12不是迭代器) 
let [a,b] = "12";          console.log(a,b);     //  "1"   "2"  字符串的包装类可以隐式将其转为类数组,比如可以以数字形式操作字符串:str[0] = 1;
let {length} = 123;        console.log(length);  //undef
let {length} = "123";      console.log(length);  // 3(数字3,非字符串)

//甚至变态到用在一些方法中:
let {pow,ceil,floor} = Math; consle.log(floor(2.3));      //     2

let {toString:n} = 123;
let {toString:b} = false;
console.log(n == Number.prototype.toString);       //true
console.log(b == Boolean.prototype.toString);      //true

function add([x,y]){return x+y;}
console.log( add([1,2]) );      //   3

4.应用:
交换两个数:let x = 1,y = 2; [x,y] = [y,x];
函数返回值的解构:function methods(){return {add:function(){},sum:function(){}}} let {add,sum} = methons();

你可能感兴趣的:(ES6)