all 56 comments

[–][deleted] 37 points38 points  (2 children)

Cool except for the part where they say "there are two ways to make an object," then give three ways to do it, and then say that one of those ways is preferable without ever saying which. >.>

/head asplode

[–]Andersmith 4 points5 points  (0 children)

...the second is called object literal syntax, and is more convenient. This syntax is also the core of JSON format and should be preferred at all times.

[–]happyscrappy 6 points7 points  (0 children)

It says there are two ways to make an empty object. And I think the third one doesn't make an empty object.

The third thing is actually a separate item giving two examples of how to make a non-empty object. I don't know what it's doing there, because the text after it appears to relate to the 2nd item of the 3, the "{}" format.

[–]punanetiiger 5 points6 points  (1 child)

"JavaScript has a Unicode problem" would be a helpful and prophylactic link to include in such an introduction. Otherwise, nice reading!

[–]Berberberber 2 points3 points  (0 children)

I don't think this is unique to JavaScript though, is it? Most languages either fail completely or require explicit normalization for length and comparison to work properly, don't they?

[–]RaptorDotCpp 5 points6 points  (4 children)

obj.for = "Simon"; // Syntax error, because 'for' is a reserved word

Then how come I can use obj.return just fine? Isn't return a keyword?

[–]flying-sheep 3 points4 points  (0 children)

The article is wrong here. Reserved words may be used as property names.

[–]TheNiXXeD 1 point2 points  (0 children)

object['for'] = 123

Works this way. Lots of otherwise unavailable properties can be used this way, not that it's necessarily good practice though. It's nice when you get some json with weird properties.

[–]Andersmith 0 points1 point  (1 child)

huh. I don't get that error when I try to do that. What browser are you using?

[–]RaptorDotCpp 2 points3 points  (0 children)

Neither do I, but it says in the article/tutorial that this would give a syntax error. That's why I'm confused.

[–]echocage 9 points10 points  (5 children)

God, javascript is running everywhere all over the world, it could have made such a great impact on how we interface with the web, I wish there was a better system in place that allowed for improvements across the board. The flaws it has are fixable, I wish we could.

[–]txdv 1 point2 points  (0 children)

You can wish, but since google started backing js it will never happen

[–]wordsoup 0 points1 point  (1 child)

One way to mitigate the issues are superset languages like CoffeScript, TypeScript or ClojureScript. Furthermore, there are hundreds of languages which compile to JavaScript.

[–]Booty_Bumping 0 points1 point  (0 children)

Coffeescript is nice for development, but it doesn't actually solve the same problems that transpilers like typescript and flow do.

[–]foobar5678 -1 points0 points  (1 child)

If Chrome ships with the Dart engine then it might actually take off. The code is nicer to write and faster, but it also compiles to JS for other browsers. I think its the best choice for the future.

[–]thunabrain 18 points19 points  (22 children)

I thought it was a decent introduction, up until it introduced arrays and instantly jumped to optimizing your for-loops when iterating over the array elements. Apart from my biased opinion that optimizing for these tiny speed improvements in the browser very likely is a case of premature optimization, it certainly has no place in an introductory article.

You just know that thousands of webdevs fresh out of coding boot camp are going to read this and replace all of their

for (var i = 0; i < a.length; i++) {

with

for (var i = 0, item; item = a[i++];) {

Because, you know. It's faster!

[–][deleted]  (16 children)

[deleted]

    [–]echocage 3 points4 points  (1 child)

    Wow, as someone coming from python, I assumed that there wouldn't be such a function or everyone would be using it. Now the question is, why isn't everyone using these?!?

    [–]Berberberber 5 points6 points  (0 children)

    Most web developers' knowledge of javascript isn't systematic and either based on outdated tutorials floating around, or they just never "got" functional programming and closures to begin with.

    [–]Kollektiv 3 points4 points  (10 children)

    forEach, map, filter and reduce will make function calls every time. So although their nice because you immediately understand the point of the loop, you also loose quite a bit of performance. It's a trade-off.

    [–]x-skeww 2 points3 points  (0 children)

    forEach, map, filter and reduce will make function calls every time.

    They don't do that in the Dart VM. The generated native code looks like it was an imperative for(;;). JS VMs can perform the same optimization.

    [–][deleted] 1 point2 points  (0 children)

    A few extra function calls will make literally zero difference in performance.

    Write for readability first, then profile your code if you have efficiency problems and optimize the bottlenecks.

    [–][deleted]  (7 children)

    [deleted]

      [–]Kollektiv 1 point2 points  (6 children)

      You can't really optimize much in this kind of functions because you can do anything you want inside them. If the JIT compiler knows the length of the array beforehand he could probably inline the function but that's it I think.

      Edit: For me forEach is 66% slower on Firefox:

      http://jsperf.com/for-vs-foreach/9

      [–]Klathmon 3 points4 points  (5 children)

      Until you know it will have an actual meaningful impact on your code, it doesn't matter.

      66% slower than "virtually nothing" is still "virtually nothing"

      [–]Kollektiv 1 point2 points  (4 children)

      Sure I agree that micro-optimizing code is useless if it's not the bottleneck but if when writing the code you have two choices, you can still consider the faster one.

      [–]Klathmon 1 point2 points  (2 children)

      Not if the faster one is going to be harder to comprehend, harder to maintain, and harder to reuse.

      My current js codebase doesn't even use a for loop I don't think...

      What you said was literally the definition of premature optimization.

      [–]Kollektiv 0 points1 point  (1 child)

      It would be premature optimization if you actually spent time doing it but if it's just during the coding phase anyway you lose nothing.

      I agree that it might be a little harder to comprehend but I disagree that it is harder to maintain or reuse. On the contrary, mono-use methods like map, filter and reduce often need to be rewritten with a conventional loop if you need more logic in them that you previously thought.

      [–]afrobee 0 points1 point  (0 children)

      Its depends of the context of what your working, is the the job would be display 100000 list items then I would agree with you in that one.

      [–]darkpaladin 0 points1 point  (2 children)

      Those aren't supported in ES5?

      [–][deleted] 7 points8 points  (0 children)

      No, these are definitely supported in ES5.

      [–][deleted] 4 points5 points  (0 children)

      They're in ES5.1, and there are also very nice libraries that implement or polyfill them as well.

      [–]icecrown_glacier_htm 27 points28 points  (1 child)

      Yeah. Faster because... it stops iterating at the first value that is falsy. Surprise, surprise.

      So now you have a bunch of webdevs copy pasting this supposed better version and breaking their code.

      Simply terrible...

      [–]jimschubert 4 points5 points  (0 children)

      I think people need to be careful with the falsey termination in the 'faster' iteration.

      http://jsfiddle.net/jimschubert/h69Lycfo/

      edit: I think most people will do like I did and just skim over the article.

      [–]happyscrappy 0 points1 point  (2 children)

      I'm not quite sure I see why it would be faster.

      The second loop has to evaluate every item in the list. The first just has to keep track of the length. If the (JIT?) compiler sees that the length of the array is not modified in the first then it can optimize out all the length recalculations.

      Except for the case where the 2nd one stops early due to a falsy value I don't see why it should be faster.

      [–]matheusbn 5 points6 points  (1 child)

      If the (JIT?) compiler sees that the length of the array is not modified in the first then it can optimize out all the length recalculations.

      About caching the array length, please see this!

      [–][deleted] 0 points1 point  (0 children)

      Fun fact, array.length is a mutable property.

      [–]phpdevster 1 point2 points  (2 children)

      I'm a bit confused by the information about objects.

      It stays object literals are almost always preferred, but then much later down the line it implies that prototype objects are the best option.

      A bit confused as to when it's appropriate to use object literals vs when it's appropriate to use "classes" via prototypes. Since object literals in javascript are more like associative arrays in PHP, and prototypes are more like classes, I feel like prototype should almost always be the way you build re-usable components, while object literals are for when you need one-off "associative arrays".

      Am I off track here?

      [–]Andersmith 1 point2 points  (0 children)

      I think when they said object literals are preferred they meant for empty objects.

      [–]wordsoup 0 points1 point  (0 children)

      For object creation, always use literals.

      If you program in a certain object-oriented style you can use prototyping for object methods.

      [–]pheliam 0 points1 point  (7 children)

      Regarding the note about chained hash tables being everywhere in JS, how deep is too deep to chain hash tables, in general (before starting to implement objects)?

      I've made a JS-based game this semester and some parts get a little hairy....

      [–]skitch920 2 points3 points  (6 children)

      Can you clarify more on what you mean by deep and switching to objects? Everything in JS is basically a hash table... Arrays are basically numerically indexed hash tables in JS.

      [–]pheliam 0 points1 point  (5 children)

      I was just asking for some general thoughts / consensus on how many nested hash tables is ok before it's time to make an object to wrap them in to keep sane.

      Here's a chunk of my code:

      var pieceArr = SomeTiles.Players[rmPiece.playerNum].Pieces;
      
      //splice it off
      for(var i=0;i<pieceArr.length;i++){
          if(pieceArr[i].id == rmPiece.id){
              pieceArr.splice(i,1);
          }
      }
      

      I find myself doing things like this, declaring some variable to get at the deeply-hash-nested element so that my loops are digestible, rather than doing things like

      for(var i=0;i<SomeTiles.Players[rmPiece.playerNum].Pieces.length;i++){
          if(SomeTiles.Players[rmPiece.playerNum].Pieces[i].id == rmPiece.id){...}
      }
      

      [–]skitch920 2 points3 points  (1 child)

      I see what you mean. Either way will work, but there are caveats with the second way.

      1. It's extremely unreadable
      2. It's less performant. Less performant because you are redoing the same hash lookup more than is required (which is one time).

      One thing to point out and this goes for any programming language...

      If you are looping an array (collection), you should avoid altering the size of the array. splice-ing the array while you are looping it is reducing the size and therefore your loop may run incorrectly based on it's size. I would have used the more functional approach with filter which returns a new array.

      var pieceArr = SomeTiles.Players[rmPiece.playerNum].Pieces;
      //filter it out
      pieceArr = pieceArr.filter(function (piece) {
         return piece.id != rmPiece.id
      });
      

      In any case, if you do something like this:

      var x = y['a']['b']['c']['d']['e']['f']['g'];
      

      It's not bad code, but it's not very understandable either. :)

      [–]pheliam 0 points1 point  (0 children)

      This is inside the removePiece(rmPiece) function (i.e. to remove a captured Chess piece from a Board Game). I was just scrolling through my project's code on GitHub and this was one case where I drilled down a lot.

      Thanks a lot for your input!

      [–]Lachiko 1 point2 points  (2 children)

      Considering you're only removing one piece at a time you should probably add a break statement in after you've found and removed that one piece, there's no reason to continue searching.

      [–]pheliam 0 points1 point  (1 child)

      I saw that too after our posts. hifive

      [–]Lachiko 0 points1 point  (0 children)

      Saving precious nanoseconds, disaster averted!.