ES6变量解构赋值

分享变量解构分2部分

  1. ES变量的声明
  2. 变量的解构概念,用法,注意事项
  3. 可能在项目遇到的应用场景

第一部分变量的声明

ES6之前

大家都了解JavaScript 中变量作用域的基本单元一直是 function,就是函数作用域,
如果创建块级作用域的话就是要声明立即调用函数

// 全局作用域
var a = 2

// 块级作用域,
(function (){
   
    var a = 3
    console.log(a)

 })()

 console.log(a)

let 声明

es新增2个声明变量 let ,const方式, 只要在任意块里用这2个声明方式声明的都市块级作用域变量,
var,function声明的还是函数作用域变量,块的标志是{...}这意味着我们只需要一对 { .. } 就可以创建一个作用域

 var a = 2;

{

  let a = 3
  console.log( a );        // 3

}

console.log( a );          // 2
const 声明

用于创建常量。块级变量声明,这个变量的值在声明时设定之后就不允许改变。 const 声明必须要有显式的初始化。如果需要一个值为 undefined 的常量,就要声明 const a = undefined 。


{
   const a = 2;
   console.log( a );     // 2
   a = 3;                     // TypeError!
}

块作用域函数

从 ES6 开始,块内声明的函数,其作用域在这个块内


{
   foo();         // 可以这么做!
   function foo() {
    // ..
   }
}

foo();          // ReferenceError

举个列子

a = 1, 每隔1秒输出a+1的值, 并赋值给a以此累加到值5为止

// 错误的
// 错误原因是 异步执行时去找 i变量,此时i的值为 
for (var i = 1; i<=5;i++) {

    setTimeout(function(){
      console.log('i=>', i)
    }, i*1000)

}

// 利用之前的块级作用域
for (var i = 1; i<=5;i++) {

      (function (i){
             //  原因相当于每次声明一个i 来实现块级
           setTimeout(function(){
               console.log('i=>', i)
           }, i*1000)
           
        })(i)

}

// 利用ES6的块级申明
for (let i = 1;i<=5;i++) {
   // 相当于每次声明 i 在块内
   setTimeout(function(){
        console.log('i=>', i)
    }, i*1000)
}
let,var,const注意事项

let,var 声明且未赋值时默认值undefined,const必须显示声明 不会默认undefined

let  name = '张三',age 
var _name = '李四',_age
const __name = '王五', __age  // 报错

let ,const 不允许重复声明

let a = 1
let a = 2  // 报错

let ,const 必须声明后使用,如在声明前调用会报错,var声明前使用值默认为undefined


console.log(a)       // undefined
console.log(b)      // 报错
var a = 0
let  b = 1

连续声明赋值可采用数组解构

  1. 对象
  2. 数组
  3. 字符串
  4. 数字
  5. 布尔
  6. 类数组 (arguments,Dom对象)
    1 . set, map
    其中字符串,数字,布尔都会有个转成对象的过程

第二部分变量解构

把这个功能看作是一个结构化赋值(structured assignment)方法
1.什么变量可解构?
2. 何时赋值?
3. 赋什么位置的值?

什么变量可使用赋值解构

可遍历的对象

对象解构

我们构造了一个手动赋值,把 foo() 返回对象中的值赋给独立变量 x 、 y 和 z ,
为了实现这一点,我们(不幸地)需要一个临时变量 tmp 。
之前

function bar() {
    return {
                x: 4,
                y: 5,
                z: 6
               };
 }
var tmp = bar(),
x = tmp.x, y = tmp.y, z = tmp.z;
console.log( x, y, z );    // 4 5 6
tmp.x 属性值赋给了变量 x ,同样地, tmp.y 赋给了 y , tmp.z 赋给了 z 。

之后

function bar() {
    return {
                x: 4,
                y: 5,
                z: 6
               };
 }
var { x, y, z } = bar();
console.log( x, y, z ); // 4 5 6

// 这里可体现啦,对象赋什么位置上的值
var {x: ban,  z: bap,  y: baz,} = bar()
console.log(ban,bap,baz)  // 4 6 5

// 先用x标识去右边对象找到值  --> 然后把值付给ban变量, source = target 
// 刚好与什么对象指定值相反 -->  target = source 

var testObj = {
     ban: x,
     bap:z,
     baz:y
   }
// 所以上面的实则是
var { x:x, y:y, z:z } = bar();
// 完全体现把对象赋给数组
var o1 = { a: 1, b: 2, c: 3 },
a2 = [];
( { a: a2[0], b: a2[1], c: a2[2] } = o1 );
console.log( a2 ); // [1,2,3]
对象嵌套解构
var o1 = { x: { y: { z: 6 } } };

var { x: { y: { z: w } } } = o1;

console.log( w ); // 6
不只是声明

在已经声明的变量中应用解构赋值就是赋值操作,不只是声明

var bar = {x: 4, y: 5,z: 6}
var x , y, z
( { x, y, z } = bar );
console.log( x, y, z );   // 4 5 6

如果省略了 var/let/const 声明符,就必须把
整个赋值表达式用 ( ) 括起来。因为如果不这样做,语句左侧的 {..} 作为语
句中的第一个元素就会被当作是一个块语句而不是一个对象

赋值表达式 ( x 、 y ,z等 ) 并不必须是变量标识符。任何合法的赋值表达式都可以。
举个栗子


var o = {x:88,y:88,z:88};
( { x: o.x, y: o.y, z: o.z } = bar() );
console.log( o.x, o.y, o.z ); // 4 5 6

可以在解构中使用计算出的属性表达式
举个例子( 应用场景 )

var which = "x",
o = {};
 ( { [which]: o[which] } = bar() );
console.log( o.x );

注意事项

对象的解构的值包括继承对象

function Parent(){
   this.child = 'child'
}
Parent.prototype = {
  parent: 'parent'
}

// 在Object.prototype上有hasOwnProperty
var obj = new Parent()
var {child,parent,hasOwnProperty} =  obj 
console.log(child, parent, hasOwnProperty)

数组的解构赋值

赋何值 --> 数组中提取值,按照对应位置,对变量赋值

以前,为变量赋值,只能都是指定值

let a = 1;
let b = 2;
let c = 3;

ES6 允许写成下面这样。

let [a, b, c] = [1, 2, 3];

嵌套数组进行解构


let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo,bar,baz)  // 1,2,3

默认赋值

默认参数值

多年以来我们实现这一点的方式是这样的,


function foo(x,y) {
   x = x || 11;
   y = y || 31;
   console.log( x + y );
}
  foo();                // 42
  foo( 5, 6 );        // 11
  foo( 5 );            // 36
  foo( null, 6 );     // 17  null被强制转换成0  11+6

  foo( 0, 42 );      // 53 <--哎呀,并非42

es6 默认参数值

function foo(x = 11, y = 31) {
     console.log( x + y );
}
foo();                             // 42
foo( 5, 6 );                     // 11
foo( 5 );                         // 36
foo( 5, undefined );        // 36 <-- 丢了undefined
foo( 5, null );                 // 5 <-- null被强制转换为0
foo( undefined, 6 );       // 17 <-- 丢了undefined
foo( null, 6 );                // 6 <-- null被强制转换为0

foo( 0, 42 );                   // 42

知识点: 在函数声明中的 x = 11 更像是 x !== undefined ? x : 11 而不是常见技巧 x || 11 ,所以
在把前 ES6 代码转换为 ES6 默认参数值语法的时候要格外小心。

再来看解构赋值的默认值

// 全为undefined时
var obj = []
var [a = 3, b = 6, c =7] =  obj
console.log(a,b,c)     // 3,6,7
// 验证
var obj = [null, false,undefined,NaN,0]
var [a = 1,b = 1,c = 1,d = 1,e = 1] = obj
console.log(a,b,c,d,e)   // 只有c为 1

字符串解构

var str = '你好世界'
var[a,b,c,d,length] = str
console.log(a,b,c,d,length)  // 你 好 世 界 4

// 中间实际有一个转换过程
var strObj = new String('你好世界')
var [aa,bb,cc,dd,length] = strObj
console.log(aa,bb,cc,dd,length)

数值的解构

var num = 1234
var {toString: s}= num
console.log(s)

// 中间实际有一个转换过程
var numObj = new Number(1234)
var {toString: s} = numObj

布尔的解构

var bool= false
var {toString: s}= bool
console.log(s)

// 中间实际有一个转换过程
var boolObj = new Boolean(1234)
var {toString: s} = boolObj
console.log(s)

第3部分项目中应用

  1. 交换变量的值
    在项目中我们可能会要备份一份数据来,处理逻辑
    之前
let a  =  '你好',b  = '世界'
console.log(a,b)
a = [a,b];
b = a[0];
a = a[1];
console.log(a,b)

es6

let a  =  '你好',b  = '世界';
console.log(a,b);
[a,b] = [b,a];
console.log(a,b);
  1. 需缓存重置数据时
    (应用场景resetCom)
  2. 提取后台接口参数
    (应用场景apiCom)
posted @ 2019-04-01 11:48  打响武昌第二枪  阅读(160)  评论(0编辑  收藏  举报