转行学前端的第 41 天 : 了解 ECMAScript 数据解构(一)

831 阅读5分钟

我是小又又,住在武汉,做了两年新媒体,准备用 6 个月时间转行前端。

今日学习目标

昨天基于搜索来基础学习严格模式.所以今天就开始基础学习解构,又是适合学习的一天,加油,小又又!!!!

今天在一篇文章中,学习了一个简洁调用console.log的方法,之前在示例文章中用的很多,感觉重复代码很多,感觉文章中这种用法,还蛮不错的~~~~


字符串

转为数组解构

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

(function (log) {
    const [a, b, c, d, e] = 'hello';
    log(a); // "h"
    log(b); // "e"
    log(c); // "l"
    log(d); // "l"
    log(e); // "o"

})(console.log)

感觉很神奇~~~~~,也就是说我之前学习的String数据结构其实也可以转成数组这样~~~


解构字符串长度

类似数组对象都有一个length属性,因此还可以对这个属性解构赋值。

(function (log) {
    const {
        length: len
    } = 'hello';
    log(len); // 5

})(console.log)

感觉很神奇~~~~~,也就是说我之前学习的String数据结构其实也可以转成对象这样~~~


数值和布尔值

解构赋值时,如果等号右边是数值布尔值,则会先转为对象

(function (log) {
    const {
        toString: s1
    } = 123;
    log(s1 === Number.prototype.toString); // true

    const {
        toString: s2
    } = true;
    log(s2 === Boolean.prototype.toString); // true
})(console.log)

上面代码中,数值布尔值包装对象都有toString属性,因此变量s1和变量s2都能取到

数值数据类型有学习过,布尔值数据类型好像没有学习过~~~


数组

基础用法

完全解构

(function (log) {
    // 基础数组解构
    const [a, b, c] = [1, 2, 3];
    log(a); // 1
    log(b); // 2
    log(c); // 3

    // 嵌套数组解构
    const [foo, [[bar], baz]] = [1, [[2], 3]];
    log(foo); // 1
    log(bar); // 2
    log(baz); // 3

    // 指定索引解构
    const [ , , third] = ["foo", "bar", "baz"];
    log(third); // "baz"

    const [x, , y] = [1, 2, 3];
    log(x); // 1
    log(y); // 3

    const [head, ...tail] = [1, 2, 3, 4];
    log(head); // 1
    log(tail); // [2, 3, 4]

    const [e, f, ...g] = ['a'];
    log(e); // "a"
    log(f); // undefined
    log(g); // []
})(console.log)

这个里面好像又出现...,感觉要找时间学习一下~~~


不完全解构

另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。

(function (log) {
    const [x, y] = [1, 2, 3];
    log(x); // 1
    log(y); // 2

    const [a, [b], d] = [1, [2, 3], 4];
    log(a); // 1
    log(b); // 2
    log(d); // 4
})(console.log)

上面两个例子,都属于不完全解构,但是可以成功。

所以,不完整解构,就是左边的变量个数和右边的不一样~~~~


设置默认值

基础使用

解构赋值允许指定默认值。

(function (log) {
    const [foo = true] = [];
    log(foo); // true

    const [x, y = 'b'] = ['a'];
    log(x);// 'a'
    log(y);// 'b'

    const [a, b = 'b'] = ['a', undefined];
    log(a);// 'a'
    log(b);// 'b'
})(console.log)

不太清楚这个默认值的使用场景


使用表达式

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

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

    const [x = f()] = [1];
    log(x);// 1
})(console.log)

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

(function (log) {
    let x;
    if ([1][0] === undefined) {
        x = f();
    } else {
        x = [1][0];
    }
    log(x);// 1
})(console.log)

这个说明有些看不太懂~~~~


引用其他变量值

默认值可以引用解构赋值其他变量,但该变量必须已经声明

(function (log) {
    const [x1 = 1, y1 = x1] = [];
    log(x1);// 1
    log(y1);// 1

    const [x2 = 1, y2 = x2] = [2];
    log(x2);// 2
    log(y2);// 3

    const [x3 = 1, y3 = x3] = [1, 2];
    log(x3);// 1
    log(y3);// 2

    const [x4 = y4, y4 = 1] = [];     // Cannot access 'y4' before initialization
})(console.log)

上面最后一个表达式之所以会报错,是因为x4y4做默认值时,y4还没有声明

感觉这个应该要注意一下~~~


注意事项

解构不成功

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


const [foo] = [];
const [bar, foo] = [1];

以上两种情况都属于解构不成功,foo的值都会等于undefined


不可遍历结构

如果等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错。

(function (log) {
    // 报错
    const [foo1] = 1;// TypeError: 1 is not iterable
    const [foo2] = false;// TypeError: false is not iterable
    const [foo3] = NaN;// TypeError: NaN is not iterable
    const [foo4] = undefined;// TypeError: undefined is not iterable
    const [foo5] = null;// TypeError: null is not iterable
    const [foo6] = {};// TypeError: {} is not iterable
})(console.log)

上面的语句都会报错,因为等号右边的值,要么转为对象以后不具备 Iterator 接口(前五个表达式),要么本身就不具备 Iterator 接口(最后一个表达式)。


函数

基础用法

基础使用

函数参数也可以使用解构赋值

(function (log) {
    function add([x, y]) {
        return x + y;
    }

    log(add([1, 2])); // 3
})(console.log)

上面代码中,函数add参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量xy。对于函数内部的代码来说,它们能感受到的参数就是xy


结合箭头函数使用

函数参数也可以使用解构赋值

(function (log) {
    const arr = [
        [1, 2],
        [3, 4]
    ].map(([a, b]) => a + b);
    log(arr); // [ 3, 7 ]
})(console.log)

设置默认值

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

函数对象参数属性使用默认值

(function (log) {
    function move({
        x = 0,
        y = 0
    } = {}) {
        return [x, y];
    }

    log(move({
        x: 3,
        y: 8
    })); // [3, 8]
    log(move({
        x: 3
    })); // [3, 0]
    log(move({})); // [0, 0]
    log(move()); // [0, 0]
})(console.log)

上面代码中,函数move参数是一个对象,通过对这个对象进行解构,得到变量xy的值。如果解构失败,xy等于默认值


函数对象参数使用默认值

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

    log(move({
        x: 3,
        y: 8
    })); // [3, 8]
    log(move({
        x: 3
    })); // [3, undefined]
    log(move({})); // [undefined, undefined]
    log(move()); // [0, 0]
})(console.log)

上面代码是为函数move参数指定默认值,而不是为变量xy指定默认值,所以会得到与前一种写法不同的结果。


注意事项

undefined就会触发函数参数默认值

(function (log) {
    const arr = [1, undefined, 3].map((x = 'yes') => x);
    log(arr); // [ 1, 'yes', 3 ]
})(console.log)

今日学习总结


今日心情

今日主要是基于搜索来基础学习解构,这个希望明天学到更多的内容~~~~

本文使用 mdnice 排版