《es6标准入门》学习笔记-第三章 变量的解构赋值

来源:互联网 发布:淘宝格子铺怎么入驻 编辑:程序博客网 时间:2024/04/30 23:13

    • 基本用法
        • 解构的例子
        • 解构不成功
        • 不完全解构
        • 解构报错
        • 默认值
    • 对象的解构赋值
    • 字符串的解构赋值
    • 数值和布尔值的解构赋值
    • 函数参数的解构赋值
    • 圆括号问题
    • 用途
        • 交换变量的值
        • 从函数返回多个值
        • 函数参数的定义
        • 提取json
        • 函数参数的默认值
        • 遍历map解构
        • 输入模块的指定方法

基本用法

按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
es6允许以下面的方法赋值

var [a,b,c]=[1,2,3]console.log(a)//1console.log(b)//2console.log(c)//3

这种写法属于“匹配模式”,只要等号左右两边的模式相同,左边的变量就会被赋予对应的值
解构赋值可以使用var let const

解构的例子

let [foo,[[bar],baz]]=[1,[[2],3]];let [,,third]=[1,2,3]let [head,...tail]=[1,2,3,4]//head=1 tail=[2,3,4]let [x,y,z]=["a"]//x="a",y=undefined z=[]

解构不成功

如果解构不成功,则变量的值等于undefined

var [foo]=[]var [bar,foo]=[1]

不完全解构

左边的模式只匹配右边的一部分

var [x,y]=[1,2,3];let [a,[b],c]=[1,[2,3],4]

解构报错

如果等号的右边不是数组(严格的来说不是可遍历的机构),那么将会报错

let [a]=1;//TypeErrorlet [b]=false;//TypeErrorlet [c]=NaN;//TypeErrorlet [d]=null;//TypeErrorlet [e]=undefined;//TypeErrorlet [f]={}//TypeError

此处内容将在13-15章详细说明,此处仅为扩展阅读
数组解构赋值要求右边的值具有Iterator接口或者转为对象后具有Iterator接口
对于set结构,也可以使用数组解构

var [a,b,c]=new Set(["a","b","c"])

只要具有Iterator接口就可以数组解构赋值

function* fibs(){    var a=0;    var b=1;    while(true){        yield a;        [a,b]=[a,a+b];    }}var [one,tow,three,four,five,six]=fibs();console.log(six);//6

默认值

解构赋值允许指定默认值

var [foo=1]=[];var [x,y=1]=["a",undefined]

如果一个右侧数组成员不严格等于undfined,则默认值不生效

var [foo=1]=[null];//null

如果默认值是一个表达式,那么这个表达式是惰性求值,即只有在用到的时候才会求值

function f(){    cosnole.log("its a function")}var [a=f()]=[1]//1

因为a能取到值,所以不进行计算

默认值可以使用其他解构赋值的变量,但该变量必须为已声明过的

let [x=1,y=x]=[]//[1,1]let [x=y,y=1]=[]//y is not defined

对象的解构赋值

解构不仅可以用于数组,还可以用于对象
对象的解构,变量和属性必须同名,才能接收到值

var {a}={a:1,b:2}//1var {c}={d:3,f:4}//undefined

如果属性名不一致的,则需要将变量写成具有相同属性名的属性的值的形式

var {foo:bar}={foo:1}//bar===1,foo===undefined

在上面的代码中,foo是没有被赋值的,而bar被赋值了。
对象解构的内部机制是,先找到同名属性,再赋值给变量,真正被赋值的是后者而不是前者。

var {foo}={foo:1}//实际为{foo:foo}={foo:1} 被赋值的是foo:foo中的后者

对象解构中被赋值的是属性对应的变量而不是模式

和数组一样,解构也可以用于嵌套的对象

var obj={    p:[        "hello",{y:"word"}    ]}let {p:[x,{y}]}=obj//p是模式,不会被赋值

嵌套赋值例子

let obj={};let arr=[];({foo:obj.prop,bar:arr[0]})={foo:123,bar:true}console.log(obj)//{prop:123}console.log(arr)//[ture]

如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错

var {foo:{bar}}={baz:'baz'}//TypeError: Cannot match against 'undefined' or 'null'

已声明的变量用于解构赋值这一块的内容,我在测试时没有发现问题,是可以正常执行的,不知是属于版本问题,还是作者有误,待考证后再补充

字符串的解构赋值

字符串会转为一个类似数组的对象进行解构赋值

const [a,b,c]="hello";//['h','e','l']const {lengh:len}="hello";//len===5

数值和布尔值的解构赋值

如果右边卫数值或者布尔值,则会先转为对象

let {toString:s}=123;console.log(s===Number.prototype.toString)//truelet {toString:y}=fale;console.log(y===Boolean.prototype.toString )//true

上面的代码中,数值和布尔值的包装对象都有toString属性,所以变量能取到值
由于null和undefined无法转为对象,所以对他们解构会报错

let {prop:x}=undefined;//TypeError: Cannot match against 'undefined' or 'null'let {prop:x}=null;//TypeError: Cannot match against 'undefined' or 'null'

函数参数的解构赋值

函数的参数也可以解构赋值

function add([x,y]){    return x+y}var arr=[1,2];add(arr)//3

函数参数的解构也可以使用默认值

function move({x=0,y=0}={}){    return [x,y]}move({x:3,y:4});//[3,4]move({x:3});//[3,0]move({});//[0,0]move();//[0,0]

注意:下面的写法会得到不一样的结果

function move({x,y}={x:3,y:4}){    return [x,y]}move({x:3,y:4});//[3,4]move({x:3});//[3,undifined]move({});//[undifined,undifined]move();//[0,0]

上面的代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到不一样的结果
undefined会出发函数参数的默认值

圆括号问题

虽然在书中提出了圆括号的处理问题,但是一般的es6编码规范提出解构语句中统一不使用圆括号,所以不在此处重点说明,如果有需求的请查看原书

用途

交换变量的值

[x,y]=[y,x]

从函数返回多个值

function example(){    return [1,2,3]}var [a,b,c]=example();function example(){    return {a:1,b:2,c:3}}var {a,b,c}=example();

函数参数的定义

方便的将一组参数和变量名对应起来

function example([x,y,z]){    return x+y+z}example([1,2,3]);function example({x,y,z}){    return x+y+z}example({z:1,x:2,y:3});

提取json

var jsonData={    id:42,    status:"ok",    data:[867,5309]}let{id,status,data:number}=jsonData;

函数参数的默认值

$.ajax=function(url,{    astnc=true,    cache=true}){}

避免了函数体内写 var foo=config.foo||’default foo’

遍历map解构

在后面讲解map时会做补充,这边仅做扩展阅读

var map= new Map();map.set('first','second');if(let [key,value] of map){    console.log(key,value)}

获取键名

for(let [key] of map){ ... }

获取值

for(let [,value] of map){ ... }

输入模块的指定方法

const {sourceMapConsumer,SourceNode}=require("resource-map")import {sourceMapConsumer,SourceNode} from "resource-map"  
0 0