Live data from Hacker News

A little bit of plain JavaScript can do a lot

jvns.ca

161–170 of 206 posts

Re: A little bit of plain JavaScript can do a lot

#161

Earlier quoted context omitted.

What XSS vulnerability? Any user can set the innerHTML of any element at any time.

> What XSS vulnerability? Any user can set the innerHTML of any element at any time. This mindset right here is exactly why XSS is still an issue. If you pull user generated content and put it in the DOM like this, you will open your users to XSS from other users. Basing your personal use DOM APIs on setting `el.innerHTML` will lead to a slip-up. Use `textContent` by default.

Often times you write code to defend against other developers who don't know any better.

Re: A little bit of plain JavaScript can do a lot

#162

What sort of automated test framework do folks use while writing vanilla JS?

If I need tests I usually reach for the same tools I’d use for testing any other JS—in my case mocha, chai, and nyc—plus jsdom and jsdom-global (so I don’t have to spin up a browser for unit tests) and chai-dom.

Re: A little bit of plain JavaScript can do a lot

#163

I agree about the nuisance of creating DOM elements. innerHTML is OK if you’re doing static content, but for anything that needs to be dynamic (untrusted input, event handlers, etc.) I have a little tiny helper library that I carry around in my head and write into projects that need it: const $T = text => document.createTextNode(text) function $E(tag, props, kids) { const elem = document.createElement(tag) for (const…

Using tagged template literals the way lit-html does is the nicest JSX-substitute I’ve seen: https://github.com/Polymer/lit-html

The downside there is you’re heavily relying on strings, which feels a bit weird for things like event handlers, which would either have to inline the function as a string or do some magic behind the scenes. The editor is also going to be less helpful in figuring out your intent when using a string-only templating system.

Re: A little bit of plain JavaScript can do a lot

#164

I agree about the nuisance of creating DOM elements. innerHTML is OK if you’re doing static content, but for anything that needs to be dynamic (untrusted input, event handlers, etc.) I have a little tiny helper library that I carry around in my head and write into projects that need it: const $T = text => document.createTextNode(text) function $E(tag, props, kids) { const elem = document.createElement(tag) for (const…

Not nearly as minimal as your example, but I like the "no build tools route" of using preact. You don't need to build your code, and you can get JSX-esque syntax and some of the niceness of React without messing with npm or webpack or any of that. https://preactjs.com/guide/v10/getting-started#no-build-tool...

You used to be able to do that with React, too. I think I still got an app running that uses the JSX transpiler you loaded in a tag...

Re: A little bit of plain JavaScript can do a lot

#165

I agree about the nuisance of creating DOM elements. innerHTML is OK if you’re doing static content, but for anything that needs to be dynamic (untrusted input, event handlers, etc.) I have a little tiny helper library that I carry around in my head and write into projects that need it: const $T = text => document.createTextNode(text) function $E(tag, props, kids) { const elem = document.createElement(tag) for (const…

Others have already mentioned that you can replace "for (const k in props) elem[k] = props[k]" with "Object.assign(elem, props)"; further to that, in modern browsers, you can replace "for (const kid of kids) elem.appendChild(kid)" with just "elem.append(...kids)" - with the added benefit that plain strings passed to .append() get turned into text nodes automatically, so you probably wouldn't need $T any more:

https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/...

Re: A little bit of plain JavaScript can do a lot

#166
post #163

Earlier quoted context omitted.

Using tagged template literals the way lit-html does is the nicest JSX-substitute I’ve seen: https://github.com/Polymer/lit-html

The downside there is you’re heavily relying on strings, which feels a bit weird for things like event handlers, which would either have to inline the function as a string or do some magic behind the scenes. The editor is also going to be less helpful in figuring out your intent when using a string-only templating system.

I don’t think it’s actually strings: the tag gets the value of the expression in ${}s and can return whatever sort of object it wants. As I understand it, it basically creates HtmlTemplate objects or some other kind of Fragment: the strings are only there for specifying the tags and static attributes.

See “tagged templates” here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Re: A little bit of plain JavaScript can do a lot

#167

I agree about the nuisance of creating DOM elements. innerHTML is OK if you’re doing static content, but for anything that needs to be dynamic (untrusted input, event handlers, etc.) I have a little tiny helper library that I carry around in my head and write into projects that need it: const $T = text => document.createTextNode(text) function $E(tag, props, kids) { const elem = document.createElement(tag) for (const…

A bit more minified/modern version of this that I'm using: function $e(t='div',p={},c=[]){ let el=document.createElement(t); Object.assign(el,p); el.append(...c); return el; } var $t=document.createTextNode.bind(document); That's 173 bytes not minified, might be useful for someone. Interestingly, the function names are exactly the same - I guess people think similarly :-)

I like how short yours is—I really must use Object.assign() more. I hadn’t heard about append(); since my original version supported IE it had to use appendChild() in a loop and I never realized there was a better option.

It looks like append() also accepts strings directly. This eliminates the need for $T, which makes things even nicer.

Re: A little bit of plain JavaScript can do a lot

#168
post #46

Earlier quoted context omitted.

I mean he is a React developer after all, less than 3 levels of abstraction is greased lightning.

As a React developer I have the strictest policy to never go lower level than the browser and I never touch other fields of computing. I started my computing career in 1986 knowing only React and I'll get to the end of it knowing nothing else.

This gotta be some kind of mistake. :) React 1986?!

Re: A little bit of plain JavaScript can do a lot

#169

I agree about the nuisance of creating DOM elements. innerHTML is OK if you’re doing static content, but for anything that needs to be dynamic (untrusted input, event handlers, etc.) I have a little tiny helper library that I carry around in my head and write into projects that need it: const $T = text => document.createTextNode(text) function $E(tag, props, kids) { const elem = document.createElement(tag) for (const…

Others have already mentioned that you can replace "for (const k in props) elem[k] = props[k]" with "Object.assign(elem, props)"; further to that, in modern browsers, you can replace "for (const kid of kids) elem.appendChild(kid)" with just "elem.append(...kids)" - with the added benefit that plain strings passed to .append() get turned into text nodes automatically, so you probably wouldn't need $T any more: https:/…

Yeah, this evolved in my head from an early version that had to support IE, so it turns out there’s a bunch of cruft in it that I hadn’t realized wasn’t necessary any more. pcr910303 posted a version which uses the same APIs you mentioned, and I think I’m going to use that one in the future.

Re: A little bit of plain JavaScript can do a lot

#170
post #123

So, question for those who are following the JS ecosystem trends more closely: Is innerHTML now officially "ok to use" again? I remember way back (when XHTML was still on the table) that innerHTML was effectively deprecated: It was still around but you weren't supposed to use it for anything new because support might be dropped at any point in "the future". It was also non-standard. Instead, you were supposed to use…

> I remember way back (when XHTML was still on the table) that innerHTML was effectively deprecated

I had heard that document.write is discouraged but not innerHTML. In fact, browsers have doubled down, by adding insertAdjacentHTML (originally only in Internet Explorer).

> Instead, you were supposed to use the DOM APIs

I tried that in an app. It turned out that IE 6 was faster with innerHTML, like literally 1,000 times faster. This was surprising because I assumed the DOM APIs were closer to the metal. Not so, at least with Internet Explorer. (With Chrome, the DOM APIs and innerHTML were about the same speed).

> standard compliance and future support

It will be supported forever, because browsers refuse to break the web. You can see them saying so when they discuss syntax for new features.

Mozilla's documentation tells you when a feature is deprecated (again, usually for a feature that was experimental and never widespread). It carries no such notice on its page for innerHTML. It does, however, carry a warning: "Warning: If your project is one that will undergo any form of security review, using innerHTML most likely will result in your code being rejected." --- https://developer.mozilla.org/en-US/docs/Web/API/Element/inn...

To me, innerHTML is sometimes useful and no more dangerous than server-side rendering. Rather than deprecating it, I wonder why browser vendors have not added a native escapeHTML function (or even better, a very short syntax) to make innerHTML safer.

Post reply on HN