ES6-解构

165 阅读5分钟

ES6

解构

对象解构

// 例1:对象解构
let node = {
    type:"id",
    name:"foo"
};
let {type,name} = node;
console.log(type);
console.log(name);

// 例2: 语法错误
let {name,type};

// 例3: 在变量定义之后用解构语法赋值
let node = {
    type:"id",
    name:"foo"
},
type = "name",
name = "xlx"; 
({type,name} = node);

// 例4: 函数传递参数时使用解构赋值
let node = {
    type:"id",
    name:"foo"
},
type = "name",
name = "xlx"; 
function outputInfo(value){
    console.log(value === node);//true
}
outputInfo({type,name} = node);

// 例5: 变量在对象中不存在,这个变量会被赋值undefined
let node = {
    type:"id",
    name:"foo"
};
let {type,name,value} = node;
console.log(value);//undefined

// 例6: 防止例5的情况出现可以为可能不存在的变量设置默认值
let node = {
    type:"id",
    name:"foo"
};
let {type,name,value=true} = node;

// 例7: 为非同名的变量赋值(解构赋值设置变量别名)
let node = {
    type:"id",
    name:"foo"
};
let {type:localType,name:localName} = node;
console.log(localType);//打印id,此时type对应被解构对象内的type,解构之后的值赋值给变量localType

// 例8: 为非同名变量赋值时设置默认值(类似例6)
let node = {
    type:"id"
};
let {type:localType,name:localName="xlx"} = node;

// 例9: 嵌套对象解构
let node = {
    type:"id",
    name:"foo",
    loc:{
        start:{
            line:1
            column:1
        },
        end:{
            line:1,
            column:4
        }
    }
};
let {loc:{start}} = node;
console.log(start.line);//1
console.log(start.column);//1

// 例10: 嵌套对象解构时设置非同名变量
let node = {
    type:"id",
    name:"foo",
    loc:{
        start:{
            line:1
            column:1
        },
        end:{
            line:1,
            column:4
        }
    }
};
let {loc:{start:localStart}} = node;
console.log(localStart.line);//1
console.log(localStart.column);//1

注意:

  1. 使用var/let/const声明解构变量时需要初始化变量!(例2)
  2. 要用一对小括号包裹解构辅助语句,因为JavaScript引擎将一对开放的花括号视为一个代码块,而语法规定:代码块语句不允许出现在解构赋值语句左侧!.(例3)
  3. 解构赋值表达式=右侧如果为null或者undefined,会抛异常!
  4. 设置变量默认值时只有当对象中没有该属性或者该属性的值为undefined时才有效!(例6)
  5. 使用嵌套解构时,形如let {loc:{}} = node;的表达式虽然在语法中是合法的,但是是无效的,这条语句什么也没做!

数组解构

// 例1: 数组解构
let colors = ["red","green","blue"];
let [firstColor,secondColor] = colors;

// 例2: 省略元素,按需提取
let colors = ["red","green","blue"];
let [ , , thirdColor] = colors;

// 例3: 解构赋值
let colors = ["red","green","blue"],
firstColor = "black",
secondColor = "purple";
[firstColor,secondColor] = colors;

// 例4: ES5中交换变量的值需要定义中间量,但是ES6中可以用解构方式实现
let a = 1,b = 2;
[a,b] = [b,a];

// 例5: 默认值
let colors = ["red"];
let [firstColor,secondColor="green"] = colors;

// 例6: 嵌套解构
let colors = ["red",["green","lightgreen"],"blue"];
let [firstColor,[secondColor]] = colors;

// 例7: 不定元素,通过不定元素把数组中剩余的值全部赋给一个变量
let colors = ["red","green","blue"];
let [firstColor, ...restColors] = colors;

注意:

  1. 数组结构是根据变量在数组中的位置进行选取,可以将其存储在任意变量中,未显式声明的变量都会被忽略,数组本身不会发生变化!
  2. 使用var/let/const声明解构变量时需要初始化变量!(与对象解构类似)
  3. 与对象解构不同,数组解构在解构赋值时不需要用小括号包裹表达式!(例3,类比对象解构的例3)
  4. 解构赋值表达式=右侧如果为null或者undefined,会抛异常!(与对象解构相似)

克隆数组

数组解构中的不定元素可以用来实现数组克隆.

ES5中的数组克隆的实现,一般使用concat().这个方法的设计初衷是连接两个数组,只是调用时不传参数,就会返回当前数组的副本.ES6中的实现如下:

let colors = ["red","green","blue"];
let [...clonedColors] = colors;

解构参数

解构参数使得参数的传递变得更清晰,并且能节省代码.

// 解构参数之前
function setCookie(name,value,options){
    options = options || {};
    let secure = options.secure,
        path = options.path,
        domain = options.domain,
        expire = options.expire;
    // 设置cookie代码
    ......
}
setCookie("type","js",{
    secure:true,
    expire:60000
});

// 解构参数之后
function setCookie(name,value,{secure,path,domain,expire}){
    // 设置cookie代码
    ......
}
setCookie("type","js",{
    secure:true,
    expire:60000
});

注意: 解构参数有一个非常需要注意的地方,在上面的例子中,如果调用setCookie()时,不传入第三个被解构的参数,相当于在操作解构时,=右边是undefined.根据之前讲过的,此时程序会抛出异常.所以参数解构时不能不传被解构参数.

但是,当被解构的参数需要被设置为可选参数时,应该怎么做?

解构参数的默认值

上面提到的问题,可以用设置参数默认值来解决.

// 被解构的参数可能不存在的情况
function setCookie(name,value,{secure,path,domain,expire}={}){
    // 业务代码
    ......
}

// 被解构参数存在,但内部属性可能不存在的情况  
function setCookie(name,value,{
    secure = false,
    path = "/",
    domain = "example.com",
    expire = 60000}){
    // 业务代码
    ......
}

// 被解构参数和内部属性都可能不存在的情况
function setCookie(name,value,{
    secure = false,
    path = "/",
    domain = "example.com",
    expire = 60000} = {
    secure = false,
    path = "/",
    domain = "example.com",
    expire = 60000}){
    // 业务代码
    ......
}

虽然第三个例子中,函数边变得很完整,但是这时候代码也出现了一定量的冗余,可读性也变差.这时候可以将默认值提取到一个独立对象中,并且使用该对象作为解构和默认参数的一部分,从而消除冗余.