Search code examples
gulpbabeljsecmascript-2016

When Gulp/Babel compiles it doesn't use properly destructuring assignment


When i compile my JS using Gulp/Babel it doesn't use destructuring assignment.

My Gulp config

gulp.task('js', function () {
    return gulp.src(myFiles)
        .pipe(babel({
            presets: ['@babel/env'],
            plugins: ["@babel/plugin-proposal-class-properties"],
        }))
        .pipe(concat('app.min.js'))
        .pipe(gulp.dest('dist'));
})

My code

const links = {
        fb: `../../dist/img/facebook.png`,
        li: `../../dist/img/linkedin.png`,
        tw: `../../dist/img/twitter.png`,
    }

    ({ fb, li, tw } = links);

The output

var links = {
    fb: "../../dist/img/facebook.png",
    li: "../../dist/img/linkedin.png",
    tw: "../../dist/img/twitter.png"
  }((_links = links, fb = _links.fb, li = _links.li, tw = _links.tw, _links));

Returns this error

app.min.js?ver=5.2.2:14 Uncaught TypeError: Cannot read property 'fb' of undefined

Did I forget something at my gulp config?


Solution

  • TL;DR: Add a semi-colon after you declare links, and declare the variables you are destructuring to.

    You are taking advantage of Automatic semicolon insertion, and if you run your code through an AST Explorer, you'll see your line of links = { ... }() is getting parsed as a CallExpression, which is invalid in this case, hence the error you are receiving.

    An example of a valid CallExpression might be:

    var a = function(v) { return v }(1); // a === 1
    
    /**
     * Parsed as:
     *
     * VariableDeclaration  VariableDeclarator  CallExpression
     * |                    |                   |
     * v                    v                   v
     * var                  a =                 function(v) { return v }(1)
     */
    

    If you add a semicolon, you will see that the { ... } gets parsed correctly as an ObjectExpression.

    However, this code will still throw a ReferenceError due to the variables not being defined and the code being run in strict mode.

    Its the same reason why this code throws an error:

    "use strict";
    
    var obj = { hello: "world" };
    hello = obj.hello; // throws a ReferenceError
    

    So you need to define the variables, I'm guessing with another const declaration.

    const links = {
        fb: `../../dist/img/facebook.png`,
        li: `../../dist/img/linkedin.png`,
        tw: `../../dist/img/twitter.png`,
    };
    
    const { fb, li, tw } = links;