ES6变量解构

分享变量解构分3部分

  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对象)
  7. 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 );
// 遍历式动态匹配
var keyArr = ['name', 'age', 'score']
var obj = {
   name: 'a',
   age: 18,
   score: 99
 }
var copyObj = {}
keyArr.forEach((v)=>{
 ({[v]: copyObj[v]} = obj)
})
console.log(copyObj)
复制代码
注意事项

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

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)
// 再次用函数验证
function abc () {}
var {hasOwnProperty:myHas} = abc
console.log(myHas === Object.prototype.hasOwnProperty) // true
复制代码

数组的解构赋值

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

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

var a = 1;
var b = 2;
var c = 3;
复制代码

ES6 允许写成下面这样。

var [a, b, c] = [1, 2, 3];
复制代码

嵌套数组进行解构

var [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)
复制代码

第三部分项目中应用

  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.vue)
  2. 提取后台接口参数 (应用场景apiCom.vue)
  3. 封装函数需大量形参时(应用场景funcCom.vue)

代码地址及附件码云百度云提取码:0uqu

转载于:https://juejin.im/post/5cad84025188251d28698aa0

你可能感兴趣的:(ES6变量解构)