js中解构的使用(变量解构,参数解构)
JS中的解构**声明:**文章取自 疯狂的技术宅前端栈晴朗的树 本文是根据前辈的内容加以学习记录。变量的解构使用变量的解构主要应用于读取访问,操作部分属性或值。下面是5个常用的变量解构操作。1、交换变量通常交换两个变量,我们会以一个中间变量来进行值的传递。这里实例的是一个简单的原始值类型,如果切换为引用值类型时候,思路是一样的。原因就在于引用值类型的变量是一个堆中的地址值,实际保存的值在栈中,系
JS中的解构
**声明:**文章取自 疯狂的技术宅 前端栈 晴朗的树 本文是根据前辈的内容加以学习记录。
变量的解构使用
变量的解构主要应用于读取访问,操作部分属性或值。下面是5个常用的变量解构操作。
1、交换变量
通常交换两个变量,我们会以一个中间变量来进行值的传递。这里实例的是一个简单的原始值类型,如果切换为引用值类型时候,思路是一样的。原因就在于引用值类型的变量是一个堆中的地址值,实际保存的值在栈中,系统为其分配的内容不会变化,我们在交换变量的时候,只是改变了指向的位置。
let a = 1;
let b = 2;
let temp;
temp = a;
a = b;
b = temp;
a; // => 2
b; // => 1
解构分配使变量交换变得简单,不需要任何临时变量:
let a = 1;
let b = 2;
[a, b] = [b, a];
a; // => 2
b; // => 1
临时在右侧构建出一个数组,存放[2,1],分别将数组中的第一项和第二项赋值给a,b。使用这种方式进行数据交换最好的地方就是:简洁,可以根据需要交换任意多个变量!至于内存回收,js自己会对不用的变量内存回收。
2、访问数组项
如果对于一个不确定的数组或其他结构类型数据,我们要获得它的某个元素,如果不存在就赋予变量默认值,通常的做法是根据该数组(结构)的.length来进行判断。
const colors = [];
let firstColor = 'white';
if (colors.length > 0) {
firstColor = colors[0];
}
firstColor; // => 'white'
数组解构是这样做的
const colors = [];
const [firstColor = 'white'] = colors;
firstColor; // => 'white'
const [firstColor =‘white’] = colors 解构将 colors 数组的第一个元素分配给firstColor 变量。如果数组在索引 0 处没有任何元素,则将分配默认值 white 。如果你只想访问第二个元素,也可以这样:
const colors = [];
const [, secondColor = 'black'] = colors;
secondColor; // => 'black'
注意结构左侧的逗号:这意味着第一个元素将被忽略。从 color 数组中为索引为 1 的元素分配了 secondColor。
相较于Array中获取数组中的部分元素 slice()方法,我们可以添加默认值。
3、不变的操作
从原数组中抽取子集数组,而上面的案例是抽取某一个元素。
const numbers = [1, 2, 3];
const [, ...fooNumbers] = numbers;
fooNumbers; // => [2, 3]
numbers; // => [1, 2, 3]
解构 [, …fooNumbers] = numbers 将创建一个新的数组 fooNumbers,其中包含除了第一项外的所有元素。numbers 数组不会发生变异,从而使操作保持不变。
除了这样操作数组,我们还可以将结构应用于对象属性上,…small解构赋值,small的数据类型取决于被解构对象,即与等号右边的变量类型保持一致,Object是实现了iterator协议的数据类型,所以可以迭代,…返回的是对象中的每一个属性,属性名自动适配右侧中的属性,组合起来就是删除了foo属性的对象。
const big = {
foo: 'value Foo',
bar: 'value Bar'
};
const { foo, ...small } = big;
small; // => { bar: 'value Bar' }
big; // => { foo: 'value Foo', bar: 'value Bar' }
需要注意的是我们在删除对象中的部分属性时候,需要知道属性名才可以,类似于一个一一映射关系。
const big = {
foo: 'value Foo',
bar: 'value Bar'
};
const { foo1, ...small } = big;
console.log(small)//{foo: 'value Foo', bar: 'value Bar'}
4、解构可迭代对象
在前面,我们将解构应用于数组。但是你可以解构实现了可迭代协议的任何对象。许多原生原始类型和对象都是可迭代的:数组、字符串、类型化数组、集合和映射。例如,你可以将字符串分解为字符:
const str = 'cheese';
const [...first] = str;
const [seconde] = str;
console.log(first);//['c', 'h', 'e', 'e', 's', 'e']
console.log(seconde);//c
不仅限于原生类型,也可以通过实现可迭代协议来自定义解构逻辑。
const movies = {
list: [
{ title: 'Heat' },
{ title: 'Interstellar' }
],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.list.length) {
const value = this.list[index++].title;
return { value, done: false };
}
return { done: true };
}
};
}
};
const [firstMovieTitle] = movies;
console.log(firstMovieTitle); // => 'Heat'
movies 对象通过定义 Symbol.iterator 方法来实现可迭代的协议。迭代器遍历电影的标题。遵循可迭代协议,可以将 movies 对象结构为标题,特别是通过读取第一部电影的标题:const [firstMovieTitle] = movies。
5、解构动态属性
通过属性对对象进行解构比对数组进行解构更为常见。
const movie = {
title: 'Heat'
};
const movie1={
};
const {
title = "hhh"
} = movie;
const {
title1 = "hhh"
} = movie;
const{title2="123"}=movie1;
console.log(title);//Heat
console.log(title1);//hhh
console.log(title2);//123
类似于键值对的解构,通过键可以从对象中拿到对应值。键不存在,以默认值为值。如果不指定默认值且在右侧没有同名键属性名,则返回undenfined。除此之外还可以使用别名:
const { identifier: aliasIdentifier } = expression;
identifier
是要访问的属性的名称,aliasIdentifier
是变量的名称,expression
应评估为对象。销毁后,变量aliasIdentifier
包含属性值。
等效代码:
const aliasIdentifier = expression.identifier;
对于用动态属性名称来解构对象:这个动态还真不是大家以为的那个动态,由于最基本的限制【键必须和被解构对象中属性名相同才可以解构出来】,这里的动态是能够类似于传参,有选择的从某一个对象中提取部分属性并返回。
const hero = {
name: 'Batman',
realName: 'Bruce Wayne'
};
const prop = 'name';
const { [prop]: name } = hero;
name; // => 'Batman'
const { [prop]: name } = hero
是一个对象分解,将变量赋给name
value hero[prop]
,其中prop
是一个保存属性名称的变量。下面是一个函数样例:
<body>
<button onclick="test1({name:'波波'},'name')"> 测试</button>
</body>
<script>
function test1(obj,nameProp){
const{[nameProp]:name}=obj;
console.log(obj)//{name: '波波'}
console.log(`hellow ${name}`) //hellow 波波
return `hellow ${name}`;
}
</script>
参数的解构
参数解构主要应用于方法中,是指兼容性更强。
传统参数顺序不能够随意放,因为每一个位置都对应实际调用函数是传入的值。
function test(val1,val2){
console.log(`第一个参数是${val1},第二个参数是${val2}`);
}
//实参和形参的顺序是一一对应的
test(1,2);
test(2,1);
多个参数记不住怎么办,这时候传递对象就可以了,对象的优势是,不用按照参数的顺序来传参,相对于参数列表传递对象属性更好记也没有强制的顺序,如果命名足够清晰在后期维护代码的时候甚至只要看属性名
就可以马上理解过来。
function infomation (user) {
// user.name
}
infomation({ name: 'xiaoer', age: 18 })
参数列表被对象替换解决了参数列表顺序的问题,可是每次调用的时候都需要从对象中取值
使得函数每次都要访问对象,带来了变量长度变长和很多无意义的赋值
。再者如果调用者不小心多传递了参数
,再不巧函数中遍历了对象这可能会产生BUG,可以利用解构赋值来解决:
function infomation ({ name, age, height }) {
console.log(name) // 药水哥
console.log(age) // 18
console.log(height) // 173cm
}
infomation ({name: ' 药水哥 ',age: ' 18 ', height: ' 173cm '})
这个时候参数并不是可选的,对于没有输入的参数选项,值默认为undefinted。
function test2({name,height,age}){
console.log(`${name},${height},${age}`)
}
test2({name:'波波'}) //波波,undefined,undefined
为了解决默认值问题:使得我们的实参跟形参关系更加松,甚至可以不输入参数
function infomation ({ name = 'anonymous', age = 0, height = 160 }) {
console.log(name) // 药水哥
console.log(age) // 0
console.log(height) // 160
}
infomation ({ name: ' 药水哥 '})
function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
函数参数重命名:
有时候需要对参数进行重命名,但是已经很多地方都使用了这个参数时。可以在函数执行最开始的时候进行重命名,但是这样显然不够 geek(主要是不够偷懒)依旧利用解构赋值
来实现重命名:
function infomation ({ name:username = 'anonymous', age = 0, height = 160 } = {}) {
console.log(name) // undefined
console.log(age) // 0
console.log(height) // 160
console.log(username) // anonymous
}
infomation()
更多推荐










所有评论(0)