Hacker News new | past | comments | ask | show | jobs | submit login

For me, adding the ending slash is just like adding semicolons at the end of javascript statements. They may be optional sometimes, but there is something to be said about consistency and clarity that comes with using them always. Less cognitive overload to boot.



Although there are certainly some similarities, trailing slash on empty tags is a different case to automatic semicolon insertion. Semicolons are mostly optional, but the trailing slash is never required, and does absolutely nothing—most specifically, it doesn’t close tags, and that’s what I’m getting at with my position of the trailing slash being mildly harmful: it’s teaching a mental model that’s simply wrong.


Code (and layout) is written for the human reader first. The machine does not care about most whitespace, should we write everything into a single line? (Some of my colleagues seem to think so.)


The name is literally a "self-closing tag", isn't it? And it's better for someone else reading: you may not recall what the tag is, but you know you don't have to look for a closing tag below.


But that’s the thing—it doesn’t do that. If you want an empty div, you can’t write <div/>, because that’s equivalent to just <div>; you’ll have to write <div></div> instead.


It’s just that some tags (like IMG) are always self-closing, some are never self closing (DIV) and some can optionally be closed (P). The trailing / just signals the reader that the tag is meant to end then and there.


Aren't they optional 100% of the time though?


Not 100%. There are a small handful of really wicked gotchas. I think there’s a lot of articles on them. I can’t find the one I like and don’t want to share one I haven’t read yet.


Here’s an example in each direction.

In this first example, ASI inserts an undesired semicolon:

  return
  {a: 0}
This returns undefined, and doesn’t continue on to execute the block containing a statement 0 with label a. (Change it to {a: 0, b: 0} and you get a syntax error because of this reinterpretation of what was intended as an object literal.)

In this second example, ASI doesn’t insert a desired semicolon:

  f()
  [].forEach.call(…)
This becomes a syntax error, because the [] has become subscripting rather than an array literal. (Incidentally, [].forEach is smelly anyway; prefer Array.prototype.forEach, maybe assign that to a constant if you’re doing it much.)


The second example could be replaced with something more common like:

    f()
    ['foo', 'bar'].forEach(...)
Which is probably a type error, except if `f()` returns something like:

    function f() {
      return {
        bar: ['Not the array', 'you were expecting'],
      }
    }
Then you would actually iterate over the returned `bar` array, not the expected `['foo', 'bar']` array.

Another fairly likely example of a desired semicolon not inserted is when the following line starts with a template string literal:

    f()
    `This is tagged with whatever f() returns`
This will most likely be a type error, except if `f()` returns a function, that function will then be called on the template string to do whatever. However I have a hard time imagining when you would want to start a statement with a template string literal without doing something smelly like:

    `some ${interpolated} string`.includes(someVar)
      ? sideEffectA()
      : sideEffectB()




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: