学习记录--《深入理解ES6》之解构

对象解构

对象解构语法在赋值语句的左侧使用了对象字面量。

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

如果想在变量声明之后改变它们的值

let node = {
		type : "Identifier",
		name : "foo"
},
		type = "Literal",
		name = 5;
		
({ type, name } = node );

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

在本例中,typename属性在声明时被初始化,而两个同名变量也被声明并初始化为不同的值。接下来一行使用了解构表达式,通过读取node对象来更改这两个变量的值。 注意 必须用圆括号包裹解构赋值语句,这是因为暴露的花括号会解析为代码块语句,而块语句不允许在赋值操作符(即等号)左侧出现。圆括号标示了里面的花括号并不是块语句、而应该被解释为表达式,从而允许完成赋值操作。

let node = {
		type : "Identifier",
		name : "foo"
},
		type = "Literal",
		name = 5;
		
function outputInfo(value){
		console.log(value === node);  //true
}

outputInfo({ type, name} = node);

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

outputInfo() 函数被使用一个解构赋值表达式进行了调用。该表达式计算结果为node,因为这就是表达式右侧的值。对type与name的赋值正常进行,同时node 也被传入了outputInfo() 函数。

当解构赋值表达式的右侧(= 后面的表达式)的计算结果为null 或 undefined时,会抛出错误。因为任何读取 null 或 undefined 的企图都会导致“运行时”错误。

默认值
当你使用解构赋值语句时,如果所指定的本地变量在对象中没有找到同名属性,那么该变量会被赋值为undefined.

let node = {
	type : "Identifier",
	name : "foo"
};
let { type, name, value } = node;

console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // undefined

//可以选择性定一个默认值
let { type, name, value = true } = node;
console.log(value); // true

赋值给不同的本地变量名

ES6有个扩展语法,允许你在给本地变量赋值时使用一个不同的名称,而且该语法看上去就像是使用对象字面量的非简写的属性初始化。

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

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

//也可以给变量别名添加默认值
let { type: localType, name: localName  = "bar" } = node;

嵌套的对象解构

使用类似于对象字面量的语法,可以深入到嵌套的对象结构中去提取你想要的数据。

let node ={
	type : "Identifier",
	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 : "Identitier",
		name : "foo",
		loc : {
			start : {
				line : 1,
				column : 1
			},
			end :{
				line : 1,
				column : 4
			}
		}
};

// 提取node.loc.start
let { loc: { start: localStart }} = node;

console.log(localStart.line);  // 1
console.log(localStart.column); //1

在此版本的代码中,node.loc,start的值被存储在一个新的本地变量localStart 上,解构模式可以被嵌套在任意深度的层级,并且在每个层级的功能都一样。

对象解构十分强大并有很多可用形式,而数组解构则提供了一些独特的能力,用于提取数组中的信息。

数组解构

数组解构的语法看起来与对象解构非常相似,只是将对象字面量替换成了数组字面量。数组解构时,解构作用在数组内部的位置上,而不是作用在对象的具名属性上。

let colors = ["red", "green", "blue"];
let [ firstColor, secondColor ] = colors;
console.log(firstColor); // “red“
console.log(secondColor); //"green"

也可以在解构模式中忽略一些项,并且只给感兴趣的项提供变量名。例如,若只想获取组中的第三个元素。

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

此代码使用了解构赋值来获取colors 的第三个项。模式中 thirdColor 之前的逗号,是为数组前面的项提供的占位符。使用这种方法,你就可以轻易从数组任意位置取出值,而无须给其他提供变量名。

与对象解构相似,在使用var、let、const 进行数组解构时,你必须提供初始化器。

解构赋值

let colors = ["red", "yellow", "green"],
	firstColor = "black",
	second = "purple";
[firstColor, secondColor] = colors;

console.log(firstColor);  //"red"
console.log(secondColor);  //"green"

与对象解构不同,不必将表达式包含在圆括号内

//在ES6中互换值
let a =1,b=2;
[a,b] = [b,a];
console.log(a);   //2
console.log(b);   //1

与对象解构赋值相同,若等号右侧的计算结果为 null 或 undefined,那么数组解构赋值表达式也会抛出错误。

默认值
与对象解构赋值一致。

嵌套的解构
与解构嵌套的对象相似,可以用类似的方式来解构嵌套的数组。在整个解构模式中插入另一个数组模式,解构操作就会下行到嵌套的数组中,就像这样

let colors = ["red",["green", "lightgreen"], "blue"];
// 随后
let [ firstColor, [secondColor] ] = colors;
console.log(fistColor); //"red"
console.log(secondColor) ; //"green"

此处的secondColor 变量指向了 colors 数组中的 “green”值,该项被包含在第二个数组中,因此解构模式就要把 secondColor 包裹上方括号。与对象解构相似,你也能使用任意深度的数组嵌套。

剩余项
类似函数的剩余参数。它使用… 语法来将剩余的项目赋值给一个指定的变量。

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

console.log(firstColor);  //"red"
console.log(restColors.length); //2
console.log(restColors[0]); //"green"
console.log(restColors[1]); //"blue"

colors 数组的第一项被赋值给了 firstColor 变量,而剩余的则赋值给了一个新的restColors数组。

//ES5 克隆数组
let colors = ["red", "green", "blue"];
let clonedColors = colors.concat();

// 在 ES6 中克隆数组
let colors = [ "red", "green", "blue" ];
let [ ...clonedColors ] = colors;

可以用于数组克隆
剩余项必须是数组解构模式中的最后部分,之后不能再有逗号,否则就是语法错误。

混合解构

对象与数组解构能被用在一起,以创建更复杂的解构表达式。在对象与数组混合而成的结构中,这么做便能准确提取其中你想要的信息片段。

let node = {
		type : "Identifier",
		name : "foo",
		loc : {
			start : {
				line : 1,
				column : 1
			},
			end : {
				line : 1,
				column : 4
			}
		},
		range : [0,3]
};
let { loc : { start }, range :[ startIndex]} = node;

console.log(start.line);  //1
console.log(start.column); //1
console.log(sstartIndex); //0

此代码将node.loc.start 与node.range[0] 提取出来,并将它们的值分别存储到start 与startIndex 中。 要记住解构模式中的loc: 与range: 只是对应于node对象中属性的位置。混合使用对象与数组解构,node 的任何部分都能提取出来。对于JSON配置结构中抽取数据来说,这种方法尤其有用,因为它不需要探索整个结构。

参数解构

解构还有一个特别有用的场景,即在传递函数参数时。当JS的函数接收大量可选参数时,一个常用模式是创建一个options 对象,其中包含了附加的参数。

// options 上的属性表示附件参数
function setCookie(name, value, options) {
	options = options || {};
	let secure = options.secure,
		path = options.path,
		domain = options.domain,
		expires = options,expires;
		//设置cookie的代码
}
//第三个参数映射到options
setCookie("type", "js",{
	secure : true,
	expires : 60000
});

很多JS的库都包含了类似于此例的setCookie() 函数。在此函数内,name 与 value 参数是必需的,而secure、path、domain与expires则不是。并且因为此处对于其余数据并没有顺序要求,将它们作为options对象的具名属性会更有效率,而无须列出一对额外的具名参数。这种方法很有用,但无法仅通过查看函数定义就判断出函数所期望的输入,你必须阅读函数体的代码。
参数解构提供了更清楚地表明函数期望输入的替代方案。它使用对象或数组解构的模式替代了具名参数。要看到其实际效果,查看下例中重写版本的setCookie()函数:

function setCookie(name, value, { secure, path, domain, expires }) {
 
		//设置cookie的代码
}
//第三个参数映射到options
setCookie("type", "js",{
	secure : true,
	expires : 60000
});

此函数的行为类似上例,但此时第三个参数使用了解构来抽取必要的数据。现在对于*setCookie()*函数的使用者来说,解构参数之外的参数明显是必需的;而可选项目存在额外的参数组中,这同样是非常明确的。

解构的参数是必需的

参数解构有一个怪异点:默认情况下调用函数时未给参数解构传值会抛出错误。例如调用上例中的setCookie()函数会出错:

//出错
setCookie("type", "js");

调用时第三个参数缺失了,因此他不出预料地等于 undefined。这导致了一个错误,因为参数解构实际上只是解构声明的简写。当 setCookie() 函数被调用时,JS引擎实际上是这么做的:

function setCookie(name, value, options){
	let{ secure, path, domain, expires } = options;
	//设置cookie的代码
}

//通过提供默认参数 解决
functuin setCookie(name. value, { secure, path, domain, expires } = {}){
	//...
}

参数解构的默认值
你可以为参数解构提供可解构的默认值,就像在解构赋值时所做的那样,只需在其中每个参数后面添加等号并制定默认值即可。

function setCookie(name, value,
{
	secure = false,
	path = "/",
	domain = "example.com",
	expires = new Date(Date.now() + 360000000)
} = {}
) {
// ...
}

总结

解构使得在JS中操作对象与数组变得更容易。使用熟悉的对象字面量与数组字面量语法,可以将数据解构分离并只获取你感兴趣的信息。对象解构模式允许你从对象中进行提取,而数组模式则能用于数组。
对象与数组解构都能在属性或项未定义时为其提供默认值;在赋值表达式右侧的值为null或undefined时,两种模式都会抛出错误。你也可以在深层嵌套的数据结构中使用对象与数组解构,下行到该结构的任意深度。
使用var,let,或const的解构声明来创建变量,就必须提供初始化器。解构赋值能替代其他赋值,并且允许你把值解构到对象属性或已存在的变量上。
参数解构使用解构语法作为函数的参数,让“options”对象更加透明。解构的参数可以是对象模式、数组模式或混合模式,并且你能使用它们的所有特性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值