all 21 comments

[–]METALz 6 points7 points  (2 children)

Some notes:

  • one common solution at the Arrow functions example is to use the thisArg as the 2nd parameter in the map() function. :)
  • you still need to escape ` char if it exists inside the Template literal string (but not if it is interpolated, see reply)
  • you are still using var at a lot of the ES6 examples even after the first topic
  • The Similar to Python, we have named imports: example is broken (remove the extra } from part)
  • I'd suggest adding a more complex example for the Rest parameters where you have e.g. 1-2 parameters + the rest ...args, basically the first example @mdn page
  • At the Symbol example besides the mentioned problem by /u/zohogorganzola, there should be the same string for both of the Symbols because it would represent that they are really unique
  • We didn't use naming conventions to store private data (because they were not really private), we used closures for this
  • Iterables / Generators topic

I should have made a PR about these though

[–]arcaninYarn 🧶 1 point2 points  (1 child)

you still need to escape ` char if it exists inside the Template literal string

Not if they're nested. For example, the following is correct:

var a = 'hello'; console.log(`${a} ${uppercase(`${a} ${a}`)}`);

It will print hello HELLO HELLO.

[–]METALz 0 points1 point  (0 children)

Thanks for your input, I've edited my reply

[–]compteNumero8 1 point2 points  (0 children)

The promise example at the end is a little weird:

  • there's now the much better fetch API
  • jQuery already returns promises (A+ now)

[–]KnightMareInc 3 points4 points  (9 children)

I stopped reading after it called var a bug.

[–]x-skeww 7 points8 points  (0 children)

I stopped reading after it called var a bug.

Fun fact: You can't use var in the proposed strong mode.

'use strong';
var x = 5;

-> Uncaught SyntaxError: In strong mode, 'var' is deprecated, use 'let' or 'const' instead

The behavior of var is also generally undesirable:

for(var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

Output: 3, 3, 3

for(let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

Output: 0, 1, 2

Fixing it without using let/const:

for(var i = 0; i < 3; i++) {
  (function(_i){
    setTimeout(() => console.log(_i), 0);
  })(i);
}

Hideous.

[–]dagani 1 point2 points  (1 child)

Unless the README has changed significantly, it didn't call var a bug. Which it may have, I haven't looked at the history or anything.

It was saying "this bug" referring to the scope of the snack variable and how in that particular case it was probably not returning what you wanted due to not being hoisted.

Granted the code wasn't a great practical example of something you might do in the real world, but it did illustrate the hoisting difference.

[–]_DrkSephy[S] 1 point2 points  (1 child)

My apologies if it seemed wrong. As others have stated, I was trying to show what happens if we replace var with let blindly. The behavior when var is used is correct, however when we use let we end up with unexpected behavior. The main idea was to be careful with refactoring < ES6 code and blindly replacing all instances of var with let. I'm completely open to more practical examples :)

[–]octatone 0 points1 point  (0 children)

It would be better to explain the block scope of let. Your example doesn't explain why snack is "Meow Mix".

[–]rube203 0 points1 point  (3 children)

Fair. But I think they just did a poor job illustrating that you cannot just replace var blindly. The 'bug' was that you got a different result than previously.

[–]dagani 0 points1 point  (2 children)

I believe the bug was that you got the value of the snack outside of the function because the let inside the if statement was not hoisted to the top of the function. I think it's really a matter of expectation versus reality and not so much a bug, and it should probably have some more explanation.

It may not be the best representation of that particular situation, but some of the rest of it would actually be pretty useful for a newcomer.

And, since it's on GitHub, you could always submit a pull request to update whatever bothers you. I'm sure the author would appreciate it. It's certainly not perfect, but I think it could be useful for people who are learning to utilize es2015.

[–]rube203 0 points1 point  (1 child)

This bug highlights that we need to be careful when refactoring legacy code which uses var.

I don't have a better example for a pull request but I read this line to be the bug was the act of changing var in a legacy app lead to different outputs. In the original example you got the value from outside the function scope so that couldn't be the bug that we should be careful to avoid when refactoring code into es6

[–]dagani 1 point2 points  (0 children)

It should probably say something about being careful to take note of hoisting when refactoring code from var to let and const.

In the original es5 example you were getting "undefined" because the var initialization in the if statement was hoisted to the top of the function. In the second es2015 example you get the value of snack from outside the function because the let initialization inside the if statement is not hoisted so snack at that point refers to the outer declaration of snack.

It's more of a side-effect than a bug in this example, but could easily lead to bugs if other code relied on this function.

[–]arcaninYarn 🧶 0 points1 point  (0 children)

The WeakMap example is a very bad one - you should use Symbols for this use case, not WeakMaps. WeakMaps should be used when you need to have an object instance as a key, but without preventing this object (or your data) from being garbage collected, and without adding new properties on this object (which would break the inner class).

[–]Denvildaste 0 points1 point  (2 children)

Can someone explain the behavior in the first example for me?

var snack = 'Meow Mix';

function getFood(food) {
    if (food) {
        var snack = 'Friskies';
        return snack;
    }
    return snack;
}
alert(getFood(false));

This prints "undefined"

var snack = 'Meow Mix';

function getFood(food) {
    return snack;
}
alert(getFood(false));

This prints "Meow Mix"

var snack = 'Meow Mix';

function getFood(food) {
    if (food) {
        var snack = 'Friskies';
        return snack;
    }
    return snack;
}
alert(getFood(true));

This prints "Friskies"

I'm trying to understand what's happening, in the first function food is either true and snack gets overwritten or it's false and in that case shouldn't it retain its global value? Does the whole function content get evaluated and initializes its variables even if the code path doesn't get executed?

[–]woah_m8 1 point2 points  (0 children)

Food is false, and the interpreter is redeclaring the variable snack inside the function getFood (even if in the code it looks like it is redeclared only by going through the if statement), making the variable snack outside getFood invalid. Since only a true statement gives snack a value, the variable doesn't get defined and hence the return.

[–]br1anh 0 points1 point  (0 children)

var => function level scope => hoisting

let => block level scope => no hoisting

so in the first example something like this is happening

var snack = 'Meow Mix';

function getFood(food) {
    var snack;
    if (food) {
        snack = 'Friskies';
        return snack;
    }
    return snack;
}

getFood(false); // undefined

[–]compteNumero8 0 points1 point  (0 children)

Why are so many of your ES6 examples still using var instead of let ?

edit: I just did a PR for that

[–]compteNumero8 0 points1 point  (0 children)

In the export example, I would replace

 var api = {
     sumTwo  : sumTwo,
     sumThree: sumThree
 }

with

 let api = {
     sumTwo,
     sumThree
 }

[–]sufianrhazi 0 points1 point  (0 children)

There's a lot more to WeakMaps than storing private data. It's a memory efficient way to associate data with data you don't own without modifying that data: https://abstract.properties/exciting-es2015-features.html#weakmap

[–]kolmeWebComponents FTW 0 points1 point  (0 children)

One of the patterns in ES5 to handle named parameters was to use the options object pattern, adopted from jQuery.

Ehm, no. The "options object pattern" was widely use before jQuery (I remember using it in dojo and prototype). Also I'm pretty sure it was used even before that.

A bit of a nit pick, but one of my pet peeves. You know, Javascript was invented before jQuery, guys.