Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I tried JS multiple times. And every time, easy things are complicated when doing them in JS. It is much easier and faster for me to do those same things in C, even though I'm equally familiar with both. This is mostly because there are just so many gotchas.

Here are some examples from this week:

Checking whether a passed argument is an array or a dict:

    var a = []
    if (Object.prototype.toString.call(a) !== '[object Array]') ...
(perhaps not js itself, but how it is used) Leaking DOM nodes are a thing: https://developer.chrome.com/devtools/docs/heap-profiling-do...

Easy things like getting values of a dictionary:

    var d = {
        a: [1,2,3,],
        b:[4,5]
    }
    var values = Object.keys(d).map(function(key){
        return d[key];
});

in Python, it's just .values()

Errors aren't thrown when there are obvious issues with the code.

String.replace replaces one instance instead of all instances in a string.

Functions arguments are a bit of a mess.

differences between

    for each (var myVar in myObject)
    for (var myVar in myObject)

random things like these:

http://stackoverflow.com/questions/2568966/how-do-i-pass-the...

All the things here:

http://www.toptal.com/javascript/10-most-common-javascript-m...

If you import a library, they could have modified the global scope. This is common in JS libraries. Then some things you wrote don't work.

undefined/null thing

differences between var declared function and regular named function.

Many things in the language are not obvious and you have to discover them through trial and error or study JS internals and find out how things are implemented.



As someone that wrote C/C++ for decades I hated JS. Now that I've gotten used to JS every time I'm forced to go back to C/C++ I hate Hate HATE IT.

Things that take 5 lines in JS take 200 in C++ all to make the type system happy. Yes I understand the trade offs. Wrote games most of my career. I used to find it cool that I could write a 400 line templated intrusive list class that generates just 1 instruction on use. Yippee. Now though I just resent the fact that have to write giant implementations like that for code who's performance doesn't matter.

In JS forgot a little piece of data? It's generally almost zero lines to hack it in. C++? It's often refactoring hundreds of lines of code.

Wanna to wrap some function to monitor it, test, sanitize, .. trivial in JS. Next to impossible without massive refactoring in C++

When I have to do C++ again I will but it won't be without kicking and screaming.


Neither C nor C++ is often thrown up as the gold standard for type systems nor expressiveness.


> Checking whether a passed argument is an array or a dict

Luckily solved in ES2015:

Array.isArray(thing)

The toString trick is pretty outdated, in ES5 you can also do:

thing instanceof Array

> (perhaps not js itself, but how it is used) Leaking DOM nodes are a thing

Definitely not JS itself, it's easy to create circular references between JS objects and DOM elements. It's just the way the DOM is (poorly) designed and the way it interacts with JS.

> for each (var myVar in myObject)

That's not even standard, just a Mozilla "dialect". I don't think that's supported by any engines other than SpiderMonkey and predecessors.


>The toString trick is pretty outdated, in ES5 you can also do:

> thing instanceof Array

instanceof is ES3.

> That's not even standard, just a Mozilla "dialect". I don't think that's supported by any engines other than SpiderMonkey and predecessors.

To quote MDC:

> The for each...in statement is deprecated as the part of ECMA-357 (E4X) standard. E4X support has been removed, but for each...in will not be disabled and removed because of backward compatibility considerations. Consider using for...of instead. (Please refer to bug 791343.)


So now we have ...

    for each (var x in a) ...  <<Firefox only??>>
    for (var x of a) ...  <<ES6>>
    for (var x in a) ...
    a.forEach(callback[, thisArg])
Knowing JS, each of them have their own quirks probably.


Yes:

for each (...) -> It's not supported anywhere, so forget it.

for (var x in a) -> x is the key, so it's kind of inconvenient. You have to watch out for inherited properties/methods so one should check for a.hasOwnProperty(x).

for (var x of a) -> It has mostly no gotchas. Only poor browser support.

.forEach only works with arrays and from ES5 on. You have the good old "this"/scope gotcha.


Array.isArray is already in ES5 and can be used in any reasonably modern browser (meaning IE9+)


Is the argument a dictionary?

    if (a instanceof Array) ...

    // or polyfill
    Array.isArray = Array.isArray || function(a) { 
      return a instanceof Array; 
    };
Object.keys can be cleanly shimmed without braking older browsers. You can always shim in the behavior you want, as long as you don't need IE7 support.

    Object.prototype.values = function() {
      var instance = this;
      return Object.keys(this).map(function(key){
        return instance[key];
      });
    }
Replacing globally in a string

    console.log("I lose and lose again, not even close.".replace(/\blose\b/g, "win"));
If you're using ES6 or node-style modules, you shouldn't generally mess with global state, unless you are polyfilling new features. Promises (bluebird), fetch, etc...

Understanding falsy values is a core part of learning JS, as is coercion... no it isn't perfect, but there are flaws in any language you can bring up.

As to a function assigned to a variable vs a function declaration, well again that's part of learning the language.... Being able to use functions as first class expressions is a very powerful feature, that frankly works pretty well.

Of the features missing from JS proper, an isolated invokable web-workers scenario with plain, side effect free functions/modules would be a great start (not the current way via secondary script).

That said, most of your complaints are things that are easier to work around, or simply things that you learn with the language. It's not that different from learning warts in Python (which is better than many), C#, Java or anything else.


Regarding Arrays:

   var iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
   xArray = window.frames[window.frames.length-1].Array;
   var a = new xArray(1,2,3);
   >> a instanceof Array;
   << false
   >> a
   << Array [ 1, 2, 3 ]
   >> Object.prototype.toString.call(a) === "[object Array]"
   << true
All I'm saying is there are way too many such things that you have to keep in mind.


See `Array.isArray` which you can polyfill however you like ... Beyond that, if you bring primitives from another frame, you kind of get what you deserve. Most likely you should check for not a string, but has `length` property that is a Number and use `Array.from` with your conditions, especially with arguments or dom collections.

Most likely when working across frames, you should use messaging, unless you're doing something truly hokey... In either case, working across frames like that is akin to poking into the memory of one process from another. It's bound to have issues...

I don't think this is something that WebAssembly would allow you to do in the first place...


You don't need to do that. You just use a library.

  import { isArrayLike, values } from 'ramda';
  
  const a = [];
  const aIsArray = isArrayLike(a);
  
  const d = {
    a: [1,2,3,],
    b:[4,5]
  };
  const dValues = values(d);
Not to mention that a lot of the problems you mention have native solutions in ES6.

JavaScript is a very different language than the one people used to use 5 years back.


Which library? From where? Never heard of ramda, but I can tell you it's not standard.

Why should people use JS with a non-standard library when dictionaries come built into better languages?


The library is ramdajs.com and it can be grabbed from npm.

I do not agree that everything should be handled with standard libraries. It's better for these things to be modular and versioned, instead of them being pulled from a big bloated standard library.

The code clearly does what was being asked in a very simple and non-broken way.

Perhaps the issue here is that non-JavaScript engineers are used to kitchensink standard libraries and avoid mixing and matching to get the best experience the ecosystem offers.


You're building a straw-man there. A standard library can certainly be made to be modular and versioned. It doesn't have to be bloated for any reason whatsoever. This is Javascript - you can chop up your scripts however you want.

The problem with mixing and matching libs is that no two JS devs do it the same. Some will even re-build the same lib that has already been built by hundreds of JS devs because NIH.


You are the one that has built a strawman.

In your universe, engineers do not talk and accidentally decide to use two libraries that do the same thing within a project.

I work with JavaScript and I rarely see this happening.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: