The "use a more functional approach" and "take advantage of ES6" are by far the biggest for me. ES6 added so much good stuff, I wouldn't consider it optional. It's better than incremental upgrades, feels almost like a different language to me.
Every language has its quirks, and while I'll keep on hating Javascript's, I'll never lose sight of the fact that if you're holding out for the perfect language, you're not going to be doing much coding.
The only transpiler I've seen that gets close in terms of quality of output is BuckleScript, that thing is damn near magic but TS has the momentum and adoption.
TypeScript has been so good and caused me so few problems that I actually look at ways of moving more bits to the frontend, it makes it pleasant to work and I think (personally) the highest praise you can give a language is that it's pleasant.
Without it you frequently run into objects passed to you after going through 10k lines of code and it becomes a wicked game to figure out which properties the object actually has at that point.
JavaScript, even ES6, is IMO crap for large codebases.
Does this object have the property I'm looking for? Did somebody overwrite it with the wrong type 5000 lines ago? Why is the prototype chain broken? Where's my damn inline documentation.
My company has abandoned JavaScript wholesale with great relief. If it was a physical object we would have tossed it off the balcony.
Writing [1,2,3].map(function(x) { return x+10 }) really doesn't bother me. I don't see what the benefit is of an arrow function. Are there other things that you like?
As the OP mentions, the inheritance stuff is just likely to cause architecture headaches. I like JavaScript's concurrency model (single threaded with callbacks) so I don't see any benefit to the async stuff.
It just seems like people added a ton of complexity to give up a few keystrokes. Transpiling and shimming and adding more control structures make your application more complicated, so there is a real cost. And keystrokes are not generally a big problem when I'm programming. I'm not in a race.
Same goes for 'arguments', though that comes up less. Basically, they're much more representative of a simple lambda than a classical function.
It's either "only syntactic sugar" or it "added a ton of complexity". To be honest, you sound like someone who's bitter because all the hard stuff you had to learn to deal with is now super simple and intuitive.
> I like JavaScript's concurrency model (single threaded with callbacks) so I don't see any benefit to the async stuff.
This sentence also demonstrates you either don't understand the concurrency model or async/await (async/await doesn't change the concurrency model).
The syntactic sugar isn't only there to save keystrokes, it also makes code easier to read and is less prone to errors.
I won't disagree about the added complexity.
const add = x => y => x +y;
...
[1,2,3,4].map(add(1));
now we are talking ;)They made a real focus on tooling and it's been widely adopted.
In intellij it's as simple as turning on the option and creating a .ts file, the identically named js file is then dropped in the same directory (by default) and you just include that.
It's about 2 minutes from start to finish to setup.
Then it's a natural progression to using https://www.typescriptlang.org/docs/handbook/tsconfig-json.h...
I mean sure if you are going with a split bundle, hot code reloading and tree shaking via webpack then there is a high start cost but ts on it's own is rather fantastic.
vscode does the same thing as intellij if you want to try it without downloading intellij.
Thus in your browser you see the code you write, you put in breakpoints as desired, and everything generally works.
I don't have much depth as to how it all works behind the scenes though, I'd love to know more.
That said, it is another thing you need to maintaining and depending on the number of transformations your code has to go through, you introduce more points where the source map can break.
Personally I'm a huge functional programming weenie for no reason I can coherently defend, so I prefer to avoid ES6 classes. But quite often they end up being the most reasonable solution to my problem, and having syntax for it is great. I just avoid them by default.
val or con would have been better.
Very true on both counts, but unfortunately the article perpetuates some of this misunderstanding.
> Where it gets interesting is when you return a function from an outer function...
Abbreviated example from the article:
var outer = function () {
var a = 1;
return function inner() {
return a;
};
};
...and that's the only example. No mention of where closures are actually most useful, and not a peep that you don't need a function that returns a function to get one. Any function call can get you a closure.I deal with this frequently on Stack Overflow. Someone asks a question where a closure is a great solution, and then someone answers with a complicated example involving a function that returns a function.
It seems to come up a lot in Google Maps API code:
var places = [
{ name:"Test", lat:10, lng:10 },
...
];
function initMap()
var map = new google.maps.Map(...);
for( var i = 0; i < places.length; ++i ) {
var marker = new google.maps.Marker(...);
// This is the complicated part:
marker.addListener( 'click', (function( marker ) {
return function() {
// This works because of the closure:
infowindow.open( map, marker );
}
})( marker ) );
}
}
It doesn't have to be done that way! You'll get a closure that works just as well if you simply call a function in the loop: function initMap()
var map = new google.maps.Map(...);
for( var i = 0; i < places.length; ++i ) {
addMarker( places[i] );
}
function addMarker( place ) {
var marker = new google.maps.Marker(...);
marker.addListener( 'click', function() {
// We have a closure here too:
infowindow.open( map, marker );
});
}
}
There are other ways to do this in modern JavaScript (such as using let inside the loop). I'm using old-school JavaScript here just to show that it could be done this simply even in the oldest browsers.Of course, the same thing can be done with forEach():
function initMap()
var map = new google.maps.Map(...);
places.forEach( addMarker );
function addMarker( place ) {
var marker = new google.maps.Marker(...);
marker.addListener( 'click', function() {
// We have a closure here too:
infowindow.open( map, marker );
});
}
}
Or with the forEach callback inline: function initMap()
var map = new google.maps.Map(...);
places.forEach( function( place ) {
var marker = new google.maps.Marker(...);
marker.addListener( 'click', function() {
// We have a closure here too:
infowindow.open( map, marker );
});
});
}
The point in each of these cases is that you don't need a function that returns a function to get a closure, but people who answer SO questions perpetuate this myth day after day.