ES6基础:变量的解构赋值

hushuo
发布于 2021-1-15 11:56
浏览
0收藏

前言
为什么要把ES6系列总结出来呢,第一个是为了加深印象,第二个就是在之后的代码中尽量将能用的新特性都用上!

如果我们以ES6的前后来区分代码风格的话,那么有关变量的部分应该是这样的

之前:

function newPoint(options) {
    const arg = options === undefined ? {} : options;
    const x = arg.x ? 0 : arg.x;
    const y = arg.y ? 0 : arg.y;
    const r = arg.r ? 10 : arg.r;
    console.log(x, y, r);
}

newPoint({x: 5, y: 5, r: 10});

之后

function newPoint({ x = 0, y = 0, r = 10 }) {
    console.log(x, y, r);
}

newPoint({ x: 5, y: 5, r: 10 });


或许你会觉得这并没有什么,除了看上去代码简洁之外并没有实际意义,事实却并非如此~

一、数组的解构赋值
首先看看最容易被人忽略的数组解构。

我们在获取获取数组内的元素时,大多是通过下标的方式arr[0],这种方式也确实方便,但针对特定的情况时,解构会大大提高你的效率

1.1 同时赋值多个变量
先来看这样一段代码:

let a = 1;
let b = 2;
let c = 3;
let d = 4;


当你需要使用a、b…时,你可能会这么做。而数组的解构可以让你用更少的代码做到同样的事。

let [a, b, c, d] = [1, 2, 3, 4];
a // 1
b // 2
c // 3
d // 4


1.2 解构嵌套数组
解构嵌套数组,就是模式匹配,只要等号两边的层级结构相同,就可以拿到对应位置的值,这在某些特定的情况十分有用。

const arr = [1, [2, 3, [4, 5, 6]]];

const [a, [b, c, [d, e, f]]] = arr;
a //1
b //2
c //3
d //4
e //5
f //6


1.3 相同“模式”的不完全解构
在1.1和1.2小节中,我们总是完整的对应数组结构来获取数据,但当我们模式相同但变量没有完全对应时,会发生什么呢?

let [a, b, c] = [1, 2, 3, 4]; // 1 2 3
let [a, b, c, d] = [1, 2, 3]; // 1 2 3 undefined
let [a, [b, c, [d, e]]] = [1, [2, 3, [4, 5, 6]]]; // 1 2 3 4 5


1.4 解构的默认值
为了防止1.3小节中出现的解构得到的值存在undefined的情况(实际开发中,也需要兼容某些数据),我们可以对其设定默认值。

let [a = true] = [];
a // true


注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null


上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined。

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

function f() {
    console.log('aaa');
}

let [x = f()] = [1];


上面代码中,因为x能取到值,所以函数f根本不会执行。上面的代码其实等价于下面的代码。

注意
数组的解构是根据它的位置(模式)对应的
解构操作允许有默认值,但一定是已经声明的。
如果等号的右边不是数组(或者严格地说,不是可遍历的结构)那么将会报错
二、对象的解构赋值
对象的解构赋值应该是我们使用的最平凡的解构操作了,先来看看基本操作:

const { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"


2.1 根据属性解构对象
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

如果变量名与属性名不一致,必须写成下面这样。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj; // 起了个别名
f // 'hello'
l // 'world'


这实际上说明,对象的解构赋值是下面形式的简写:

let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };


模式foo的值复制给变量foo,真正被赋值的是后者,而不是前者。

注意
对象解构和数组解构一样,都支持嵌套解构
对象解构同样支持默认值
三、函数参数的解构赋值
利用解构优化函数调用时中场景:

3.1 解构对象类型参数

function fetch(option){
    var name = option.name;
    var age = option.age;
    var like = option.like;
}

// ES6

function fetch({ name, age, like }) {
    // 参数经历了 let { name, age, like } = option
}


3.2 解构数组类型参数

const arr = [
    [1, 1],
    [2, 2],
    [3, 3],
    [4, 4]
];
const newArr = arr.map(([x, y]) => x + y);
newArr // [ 2, 4, 6, 8 ]


3.3 为参数设定默认值
设定默认值,可以避免许多拿不到数据的情况

function func({ name = '余光', age = 23, like = 'FE' }) {
    console.log(name, age, like);
}
const options = { name: '余光' }
func(options);


四、常见的使用场景
变量的解构赋值用途很多。

4.1 交换变量的值(虽然没用过,但看起来很好用)

let x = 1;
let y = 2;

[x, y] = [y, x];


上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰。

4.2 从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

返回一个数组

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


返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();


4.3 函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});


4.4 提取 JSON 数据
解构赋值对提取 JSON 对象中的数据,尤其有用。

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

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]
// 上面代码可以快速提取 JSON 数据的值。


4.5 函数参数的默认值

jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {
  // ... do stuff
};


指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || ‘default foo’;这样的语句。

更多的解构场景,基本上都是在上面的基础上略作改动,希望大家能看到它的闪光点哦~

最后提一句,既然到此我们已经了解了解构赋值,不妨在之后的代码中完全使用它!!!

 

收藏
回复
举报
回复
    相关推荐