Hacker News new | ask | show | jobs
by chrismorgan 2010 days ago
I like the createElement/appendChild-and-return-child and set-innerHTML-and-return-child combinations, they’re just the right level of repetition for minification.

As it stands, the use of innerHTML is bad, because it allows an injection attack (which amuses me given you said “no HTML injection”—though I know what you meant by that); you should use innerText instead. (You should always think very carefully before setting innerHTML or doing other similar tricks like the insertAdjacentHTML that I used in mine.)

There’s also some low-hanging fruit for golfing here:

• appendChild can be replaced with append (this sheds IE support, which I think is reasonable).

• You have arrow functions containing only a return statement; there’s a form that returns the expression: `a => { return b; }` can be written as just `a => b`. Also often in such golfing exercises if you have a function that has no return value, you can just drop the braces and let it return a value anyway, for two characters of savings.

• I said I liked the b and c functions, but it turns out that merging them ends up saving 7 characters in this case, because all but one of the invocations uses both.

Beyond that, I object strenuously to the use of <a onclick=…>+</a> for what is functionally a button, as it’s completely inaccessible to screen readers and the likes (it’s not focusable, isn’t announced as anything, and it doesn’t respond to the keyboard). Use <button> instead.

Here’s where I am on yours, 253 characters:

  a=document;b=(d,t,v)=>(d.append(d=a.createElement(t)),d.innerText=v,d);i=b(x=a.body,"input");b(x,"button","+").onclick=_=>b(o,"li",i.value).onclick=(e)=>e.target.style.textDecoration="line-through";o=b(x,"ol");b(x,"button","X").onclick=_=>o.innerText=""
1 comments

Nice finishing touch. I think this is the shortest it could get in this approach with semantic tags.

I just learnt about insertAdjacentHTML & last variable return of arrow functions. (not using widely due to compatibility)

Also, you're absolutely right about XSS & Button. I thought innerText only removing text, keeping the <li></li> :)

So, learnt some new stuff. Thank you!

In your code, the <ol> initially outputs "undefined". So we need to change it to o=b(x,"ol","") there.

Final code: a=document;b=(d,t,v)=>(d.append(d=a.createElement(t)),d.innerText=v,d);i=b(x=a.body,"input");b(x,"button","+").onclick=_=>b(o,"li",i.value).onclick=(e)=>e.target.style.textDecoration="line-through";o=b(x,"ol","");b(x,"button","X").onclick=_=>o.innerText=""

> last variable return of arrow functions. (not using widely due to compatibility)

It’s not last variable return such as you get in expression-oriented languages like Ruby or Rust; rather, it’s that if what follows the fat arrow is not a curly brace, it’s parsed as an expression, which is made to be the value returned. So `a => { a }` is the void function, but `a => { return a }` and `a => a` are identity functions. Expressed as an approximate grammar, it’s

  arrow-function = arrow-function-parameters "=>" ( "{" *statement "}" | expression-minus-object-literals )
All forms of arrow functions were introduced at the same time, in ES6 (roughly meaning “everything since but excluding IE”). `a => { return a; }` has identical browser support to `a => a`, so if you use arrow functions you might as well switch to the expression form.