Skip to content

Instantly share code, notes, and snippets.

@yang-wei
Last active April 23, 2025 00:35
Show Gist options
  • Save yang-wei/3d35e8692dbc6cc0f98d to your computer and use it in GitHub Desktop.
Save yang-wei/3d35e8692dbc6cc0f98d to your computer and use it in GitHub Desktop.

Revisions

  1. yang-wei revised this gist Jan 13, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -248,7 +248,7 @@ export default function compose(...funcs) { // here, a list of function(s) is
    ```

    To simplify how the `args` being changed:
    ```
    ```js
    function inspect(...args) {
    // when this function is called
    // args = ["a", "b", "c"]
  2. yang-wei revised this gist Jan 13, 2016. 1 changed file with 38 additions and 0 deletions.
    38 changes: 38 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    We will first discussed how destructing and rest parameters can be used in ES6 - in arrays and objects. Then we will look at a few examples and also discuss some quiz.

    ### arrays

    ```js
    @@ -63,6 +65,23 @@ var a = 1, b = 2;
    [b, a] = [a, b];
    ```

    If you had writing some JavaScript before, here is how you used to access arguments passed into a function.
    ```js
    function foo() {
    return Array.prototype.slice.call(arguments, 0);
    }

    foo(1,2,3,4,5) // [1, 2, 3, 4, 5]
    ```
    We can now refactor it into a shorted code:
    ```js
    function foo(...args) {
    return args;
    }

    foo(1,2,3,4,5) // [1, 2, 3, 4, 5]
    ```

    ### Object
    ```js
    var object = {a: "A", b: "B", c: "C"};
    @@ -153,6 +172,25 @@ console.log(length)
    // 1 because a.length = 1
    ```

    We used to write long code like this:
    ```js
    var John = {name: "John", age: 20};
    var Marry = {name: "Marry"};

    function getAge(person) {
    age = person.age || 18 // default value
    return age
    }
    getAge(John); // 20
    getAge(Marry); // 18
    // with es6
    function getAge({age = 18}) {
    return age
    }
    ```

    ### Example

    Let's see some pratical usage.
    Eg: optional arguments for functions
    ```js
  3. yang-wei revised this gist Jan 13, 2016. 1 changed file with 48 additions and 1 deletion.
    49 changes: 48 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -19,12 +19,18 @@ var [a, b, c] = array;
    console.log(a, b, c)
    // -------- 1 2 3

    // rest
    // rest parameter
    var [a, b, ...c] = array;
    console.log(c);
    // [3, 4]
    ```

    However when using rest parameter, you must apply it as the last argument.
    ```js
    var [...head, d] = array;
    // Uncaught SyntaxError: Unexpected token...
    ```

    When destructing variable exceeds its matched array, undefined is returned
    ```js
    var [a, b, c, d, e] = array;
    @@ -215,7 +221,48 @@ function inspect(...args) {
    inspect("a", "b", "c")
    ```

    ### Quiz
    @kangax published an [ES6 JavaScript quiz](http://perfectionkills.com/javascript-quiz-es6/) and there are fews related to destructing and rest. Let's have fun with them.


    #### Question 3
    ```js
    let x, { x: y = 1 } = { x }; y;
    ```
    Let break it down piece by piece:
    ```js
    let x, // x = undefined
    { x: y = 1 } = { x }
    // here a new variable y is created with default value 1
    // but since x is undefined on right hand side
    // we can think of it as
    // { x: y = 1 } = { }
    y; // when we call this y returns 1
    ```

    #### Question 7
    ```js
    [...[...'...']].length
    ```
    First I was scared by the syntax. But the `'...'` is actually a string. To make it clear:
    ```js
    [...[...'str']]
    ```
    Since string is iterable so `...'str'` will give us `["s", "t", "r"]`.
    Then the next spread `[...["s", "t", "r"]]` will give us `["s", "t", "r"]`.
    So the answer is clear.

    #### Question 11
    ```js
    ((...x, xs)=>x)(1,2,3)
    ```
    As stated above in the array section, rest parameter only can be applied as the last argument. So this will throw us error.

    ### Conclusion
    That's all for now, I hope you enjoy the discussion.

    * [Gist - Several demos and usages for ES6 destructuring](https://gist.github.com/mikaelbr/9900818)
    * [ES6 JavaScript Destructuring in Depth](https://ponyfoo.com/articles/es6-destructuring-in-depth)
    * [Why Destructuring is a Terrible Idea in ES6](http://teeohhem.com/why-destructuring-is-a-terrible-idea-in-es6/)
    * [redux](https://github.com/rackt/redux)
    * [ES6 quiz](http://perfectionkills.com/javascript-quiz-es6/)
  4. yang-wei revised this gist Jan 13, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -218,3 +218,4 @@ inspect("a", "b", "c")
    * [Gist - Several demos and usages for ES6 destructuring](https://gist.github.com/mikaelbr/9900818)
    * [ES6 JavaScript Destructuring in Depth](https://ponyfoo.com/articles/es6-destructuring-in-depth)
    * [Why Destructuring is a Terrible Idea in ES6](http://teeohhem.com/why-destructuring-is-a-terrible-idea-in-es6/)
    * [redux](https://github.com/rackt/redux)
  5. yang-wei created this gist Jan 13, 2016.
    220 changes: 220 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,220 @@
    ### arrays

    ```js
    var array = [1, 2, 3, 4];
    var nestedArray = [1, 2, 3, 4, [7, 8, 9]];

    var [a, b, c, d] = array;
    console.log(a, b, c, d)
    // -------- 1 2 3 4

    var [a, , , d, [x, y, z]] = nestedArray;
    console.log(a, d, x, y, z)
    // -------- 1 4 7 8 9
    ```

    We don't have to match the full array
    ```js
    var [a, b, c] = array;
    console.log(a, b, c)
    // -------- 1 2 3

    // rest
    var [a, b, ...c] = array;
    console.log(c);
    // [3, 4]
    ```

    When destructing variable exceeds its matched array, undefined is returned
    ```js
    var [a, b, c, d, e] = array;
    console.log(e);
    // undefined
    ```

    But we can always back it up by set its default value
    ```js
    var [a, b, c, d, e = 5] = array;
    console.log(e);
    // -------- 5
    ```

    We can clone array easily
    ```js
    var [...clonedArray] = array;
    console.log(clonedArray);
    // [1, 2, 3, 4]

    // clone the nested one
    var [,,,, [...clonedNestedArray]] = nestedArray;
    console.log(clonedNestedArray);
    // [7, 8, 9]
    ```

    Swap variable like a boss
    ```js
    var a = 1, b = 2;
    [b, a] = [a, b];
    ```

    ### Object
    ```js
    var object = {a: "A", b: "B", c: "C"};
    var nestedObject = {a: "A", b: "B", c: "C", x: {y: "Y", z: "Z"}};

    var {a: A, b: B, c: C} = object;
    console.log(A, B, C);
    // ------ "A" "B" "C"

    var {a: A, b: B, c: C, x: X} = nestedObject;
    console.log(X);
    // {y: "Y", z: "Z"}
    ```

    When we only need a value
    ```js
    var {b: B} = object;
    console.log(B);
    // ------- "B"
    ```

    Similar to array, we can set a default value
    ```js
    var {b: B, d: D = "D"} = object;
    console.log(B, D);
    // ------- "B" "D"

    // and it returns undefined when keys are not match
    var {a: A, b: B, d: D} = object;
    console.log(A, B, D);
    ```

    For everytime we have to write { keys: newVariable } explicit this is very verbose. Let's enter short hand method:
    ```js
    var {a, b, c} = object;
    console.log(a, b, c);
    // -------"A" "B" "C"
    ```

    It might seems confuse at first but this is the short hand of
    ```
    var {a: a, b: b, c: c} = object;
    // new variables a, b, c are created
    ```
    Do not use short hand method if you want to create different variable name.

    Continueing on other examples:
    ```js
    var object = {a: "A", b: "B", c: "C"};
    var nestedObject = {a: "A", b: "B", c: "C", x: {y: "Y", z: "Z"}};


    var {a, b, c, x} = nestedObject;
    console.log(x);
    // { y: "Y", z: "Z" }


    var {b} = object;
    console.log(b);
    // ------- "B"

    var {b, d = "D"} = object;
    console.log(d, d);
    // ------- "B" "D"

    // and it returns undefined when keys are not match
    var {a, b, d} = object;
    console.log(a, b, d);
    // ------- "A" "B" undefined
    ```

    Using rest in object destructing failed =(
    ```js
    // error
    // var {a: A, b: B, c: ...C} = object;
    // console.log(A, B, C); <-- error
    // use the shorthand method

    var {a, b, ...c} = object; // es7
    console.log(c);
    // {c: "C"}
    ```

    // be careful with some reserved property name
    ```js
    var [length] = ["a", "b", "c"];
    console.log(length)
    // 1 because a.length = 1
    ```

    Let's see some pratical usage.
    Eg: optional arguments for functions
    ```js
    function sum(...numbers) {
    return numbers.reduce((n, total) => {
    return n + total
    }, 0);
    }
    sum(); // 0
    sum(1, 2, 3); // 6
    sum(1, 2, 3, 4, 5); // 15

    // more abstraction <-- out of topic
    function math(equation, ...numbers) {
    return numbers.reduce((n, total) => {
    return equation.call(null, n, total);
    });
    }

    const add = (a, b) => { return a + b; }
    let sum1 = math(add, 1, 2, 3, 4);
    // 10

    const times = (a, b) => { return a * b; }
    let product1 = math(times, 1, 2, 3)
    // 6
    ```

    #### Example on OSS
    Let's look at some example on some great open source project - [redux](https://github.com/rackt/redux).
    In redux source code there is a utils function - [`compose`](https://github.com/rackt/redux/blob/d2969b5e5a1fcc1489feec0a4fcc06f92e1a3e6b/src%2Fcompose.js) which is used to turn our verbose code into a nicer one.
    ```js
    function (arg) { return fn1(fn2(fn3(arg))); }
    ```
    into
    ```js
    function(arg) { compose(fn1, fn2, fn3)(arg) }
    ```
    Here is the shorten source code and explaination
    ```js
    export default function compose(...funcs) { // here, a list of function(s) is expected: fn1, [fn2, fn3...]
    return (...args) => { // it return a composed function which expects a list of argument(s): arg1, [arg2, arg3... ]
    // args is now an array: args = [arg1, arg2, ...]
    const last = funcs[funcs.length - 1]
    const rest = funcs.slice(0, -1)

    return rest.reduceRight((composed, f) => f(composed), last(...args))
    // the first part in reduce right is not so interesting, we just keep chaining functions
    // in the second part - last(...args)
    // since our last function will accept argument like last(arg1, arg2...) instead of last([arg1, arg2...])
    // we turn [arg1, arg2, ...] into arg1, arg2, ...
    // by using rest
    }
    }
    ```

    To simplify how the `args` being changed:
    ```
    function inspect(...args) {
    // when this function is called
    // args = ["a", "b", "c"]
    console.log(args) // ["a", "b", "c"]
    console.log(...args) // "a" "b" "c"
    }
    inspect("a", "b", "c")
    ```

    * [Gist - Several demos and usages for ES6 destructuring](https://gist.github.com/mikaelbr/9900818)
    * [ES6 JavaScript Destructuring in Depth](https://ponyfoo.com/articles/es6-destructuring-in-depth)
    * [Why Destructuring is a Terrible Idea in ES6](http://teeohhem.com/why-destructuring-is-a-terrible-idea-in-es6/)