《深入浅出ES6》读书笔记(五):解构——使数据访问更便捷

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43624878/article/details/102688503

我们都知道,对象和数组字面量是JavaScript中两种最常用的数据结构,神似json。(随着json的普及,他们的作用越来越大了)
解构,就是一种打破数据结构,将其拆分为更小部分的过程。

来看一个程序:

let options={
	repeat:true,
	save:false
};
//从对象中提取数据
let repeat=options.repeat,
	save=options.save;

现在看来是没什么,但是如果options里面还包含着嵌套结构,就必须更深入地挖掘整个数据结构。而从某位大牛那里得知,这是一件极其“费力不讨好”的事情。

对象解构

对象解构的语法形式是在一个赋值操作符的左边放置一个对象字面量:

let code={
	type:"Inden",
	name:"foo"
};
let {type,name}=code;
console.log(type);   // "Inden"
console.log(name);   // "foo"

显而易见,code.type的值被存储在名为type的变量中;code.name的值被存储在名为name的变量中。
type 和 name 都是局部声明的变量,也是用来从“options对象”读取相应数据的属性名称。

如果使用let、var、const解构声明变量,则必须要提供初始化程序(也就是等号右侧的值)。

对象解构赋值

前面说了解构,那么我还想去赋值,去在定义了变量之后想改变他们的值。
我们同样可以在给变量赋值时使用解构语法:

let node={
	type:"Inden",
	name:"foo"
};
let type="Hallo";
let name="5";

//使用解构语法为多个变量赋值
({type,name}=node);

console.log(type);   // "Inden"

我们甚至可以给函数传解构赋值表达式参数:例如,在验证解构赋值表达式的值与表达式(即:=)右侧的值是否相等。

let node={
	type:"Inden",
	name:"foo"
};
let type="Hallo";
let name="5";

function ourtput(value){
	console.log(value === node);   // true
}

ourtput({type,name}=node);

console.log(type);   // "Inden"
console.log(name);   // "foo"

由于JavaScript表达式的值为右侧的值,因而此处传入的参数等同于node,且变量type和name被重新赋值,最终是将node传入ourtput()函数。

当然,如前所说:当指定的属性不存在时,可以随意定义一个默认值,在属性名称后添加一个等号和相应的默认值即可。

let node={
	type:"Inden",
	name:"foo"
};
let {type,name,value=true}=node;
console.log(type);   // "Inden"
console.log(value);   // true

非同名变量
前面所说的let后{}里的东西是不是稍有些疑惑?其实他们就是ES6的一种简写形式——对象和属性值相同时可以简写为一个(事实上,这在很多地方都有用到,比如:vue和微信小程序)。
我们当然可以另外寻找一个变量名,不过,可要注意了:

let node={
	type:"Inden",
	name:"foo"
};
let {type:localType,name:localName}=node;

console.log(localType);   // "Inden"
console.log(localName);   // "foo"

type:localType的语法含义是:读取名为type的属性并将其值存储在变量localType中,这种语法实际上与传统对象字面量的语法相悖。

嵌套对象解构

前面说解构语句就是为了防止嵌套的麻烦,可算说到这了。

let node={
	type:"Inden",
	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

没看懂的再看两遍再往下看!

在上面实例中,我们在解构模式中使用了花括号,其含义为在找到node对象中的loc属性后,应当深入一层继续查找start属性。
所有冒号前的标识符都表示在对象中的检索位置;如果冒号后是花括号,则意味着要赋予的最终值嵌套在对象内部更深的层级中。

我们继续不用简写形式:

let node={
	type:"Inden",
	name:"foo",
	loc:{
		start:{
			line:1,
			column:1
		},
		end:{
			line:1,
			column:4
		}
	}
};
//提取node.loc.start
let {loc:{start:localStart}}=node;
console.log(localStart.column);   // 1

数组解构

与对象解构的语法相比,数组解构可就简单多了,它使用的是数组字面量,且解构操作全部在数组内完成。

let colors=["red","green","blue"];
let [first,second]=colors;
console.log(first);   // "red"
console.log(second);   // "green"
let colors=["red","green","blue"];
let [,,third]=colors;
console.log(third);   // "blue"

数组的解构赋值

数组解构也可用于赋值上下文,但不需要用小括号包裹表达式

let colors=["red","green","blue"];
let first="black";
let second="purple";   //定义了
[first,second]=colors;   //修改值
console.log(first);   // "red"

哦对,说到数组解构赋值,就不得不说 “ 交换变量的值 ”:
在以前的方式里,“中间变量”貌似是不可或缺的,但是在解构赋值语句里,就不再需要额外变量了:

let a=1,b=2;
[a,b]=[b,a];
console.log(a);   // 2
console.log(b);   // 1

在这个实例中,数组解构赋值看起来就像是一个铜镜:赋值语句左侧与其他数组解构示例一样,是一个解构模式;右侧是一个为交换过程创建的临时数组字面量。
先解构临时数组,将b和a的值复制到左侧数组的前两个位置,最终结果是变量互换了他们的值。
(但如果右侧数组解构赋值表达式的值为null或undefined,则会导致程序抛出错误——这一特性与对象解构赋值很相似)

在数组中,也可以通过…语法将数组中的其余元素赋值给一个特定的变量。(这时,这个变量无限相似于“数组”)

let colors=["red","green","blue"];
let [first,...rest]=colors;   //注意这里,不定元素前面要加let
console.log(first);   // "red"
console.log(rest.length);   // 2
console.log(rest[0]);   // "green"

对了,在JavaScript设计之初,并没有想到 数组复制(拷贝) 的功能,以至于在ES5中,我们常常用 concat() 来克隆数组:

var colors=["red","green","blue"];
var clonedColors=colors.concat();

console.log(clonedColors);   // "[red,green,blue]"

concat()方法设计的初衷是为了连接两个数组,但如果调用时不传递参数就会返回当前数组的副本。
在ES6中,我们可以借助 不定元素 语法来实现相同功能:

let colors=["red","green"];
let [...cloned]=colors;

console.log(cloned);   // "[red,green]"

在被解构的数组中,不定元素必须为最后一个条目。(事实上,在不定参数函数等语法结构中都应是这样…)

类数组对象
类数组对象与数组非常相似。他们通常都有编号元素和长度属性。但是,两者有一个至关重要的区别:类数组对象没有任何数组函数。
类数组对象包含主要有DOM方法返回的HTML节点列表,和每个JS函数和少部分其他函数自动生成的参数变量。
使用与克隆数组相同的语法,可以使用延伸操作符将类数组结构转换为数组——这可以代替使用Array.from的方法:

const nodeList=document.getElementsByClassName('mydiv');
const array=[...nodeList];

console.log(nodeList);
console.log(array);

解构参数

我们还从ES5的一道例题说起:

function setCookie(name,options){
	options=options || {};
	let secure=options.secure,
		path=options.path,
		domain=options.domain;
	
	//设置cookie代码
}
setCookie("type",{
	secure:true,
	domain:6000
});

我们当然可以这么做:

function setCookie(name,{secure,domain,expires}){
	
	//设置cookie代码
}
setCookie("type",{
	secure:true,
	domain:6000
});

使用解构语法代替了第2个参数来提取必要的信息。

如果希望将解构参数定义为可选的,那么久必须为其提供默认值来解决这个问题:

function setCookie(name,value,{secure,path,domain}={}){
	//...
}

也可以“手动为其每个解构参数”添加默认值。

猜你喜欢

转载自blog.csdn.net/qq_43624878/article/details/102688503