5 ms·
How would you replace the classic `Array.prototype.map.call($nodeList, myFn)` with arrows and splat?
by hajile 5y ago
How would you replace the classic `Array.prototype.map.call($nodeList, myFn)` with arrows and splat?
- nicoburns 5y agoYou could do it like this: const mapNodeList = (...nodeList) => nodeList.map(myFn); mapNodeList(...$nodeList)
- hajile 5y agoThat creates an entire extra list of garbage.
- chrisseaton 5y agoDoesn’t the compiler optimise it away?
- hajile 5y agoThose aren't the same types. One is a DOM array and the other is a JS array. They don't share the same constructor or the same prototype chain.
- lhorie 5y agoconst mapNodeList = (...nodeList) => nodeList.map(myFn); mapNodeList(...$nodeList) Garbage collection really isn't the biggest of concerns here considering this code is susceptible to a stack overflow...
- kevincox 5y agoOr simply [...nodeList].map()
- moron4hire 5y agoI don't think you can use splats with a NodeList. At least, the TypeScript compiler complains about it.
- edflsafoiewq 5y agoWorks for me. Splats work for any iterable.
- webstrand 5y ago`[ ...document.body.childNodes ]` is legal. You need to have the `DOM.Iterable` enabled in your compilerOptions.libs` for TypeScript to permit it, though.
- Jcampuzano2 5y agoYou can do it without either of those with this: Array.from(nodeList$).map(myFunc) or if you want to spread [...nodeList$].map(myFunc)
- hajile 5y agoThat creates a new array that must be GC'd.
- Jcampuzano2 5y agoSure if you want to get nitty gritty, but you just asked how to replace it in the context of someone saying you can go without call and apply, which both of these do with the same input and output. Unless your nodelist is insanely large, this is going to be a trivial GC to perform.
- IggleSniggle 5y agoYou know, people say stuff like this a lot, and I used to believe it. But the web just feels like it’s getting slower, grinding up CPU. I think in aggregate, this stuff does matter and it’s just wishful thinking to say it doesn’t. It’s like at some point as a profession we took the mantra of “don’t prematurely optimize” as an excuse. Honestly, js feels like a much better language today, especially with ts, and hopefully there are improvements that can be made with modern approaches at the JIT layer, but until then, I’d love it if we could just have a more performant web. It might not matter to you on your powerful dev machine, but it does to me now that I’ve given up the powerful dev machine.
- gassiss 5y agoany loop in a few hundred elements is going be trivial regardless of the amount of work you do. I don't think the web is getting slower because we're using more map() instead of for...of loops. It's getting slower because what is being developed is getting more complex. Feature bloat and excessive network load are the main reasons that the web feels slower imo.
- Arnavion 5y agoIf the goal is to call functions on things whose prototype does not define them, then yes arrow functions cannot replace `call` and `apply`. They can't replace `bind` in such a situation either, but the precondition of this subthread was where `bind` can be replaced with an arrow function, ie the bound function is being called on the same `this` in the first place.
- guntars 5y agoYou should forget about that too. It's applying a function from one object to something else that it wasn't designed for. It happens to work in this case because $nodeList and Arrays are both array-like, but that's a lucky happenstance.
- bluepnume 5y agoRight. If NodeList is compatible with Array methods, it honestly feels like it should just inherit those methods. Or implement them separately.
- megous 5y agoYou can just copy them to NodeList prototype.
- sgentle 5y agoArray prototype methods are designed to be applied to other objects. There's explicit language about it dating back to the first edition of the ECMAScript spec: "The map function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method."
- guntars 5y agoYep, I just looked it up and it does indeed say that, at least for the 2016 version when all of these features were introduced. Fine! Carry on applying your maps to your non-Arrays! Personally I think Array.of($nodeList).map(…) should be guaranteed to allocate once and then there’d be no more discussion here. https://262.ecma-international.org/7.0/#sec-array.prototype.map https://262.ecma-international.org/7.0/#sec-array.prototype....
- bluepnume 5y agoThe fact that NodeList doesn't have a native map feels to me like a wart, and doesn't really justify `Array.prototype.map.call` having to exist as a fallback in the language.
- lhorie 5y ago> The Array.from() static method creates a new, shallow-copied Array instance from an array-like or iterable object[0] So, do this instead: Array.from($nodeList, myFn) [0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- merrywhether 5y agoI never knew this mapping variation of Array.from, that is slick! Also serves as a great example of how JS is standardizing useful patterns that were previously accomplished via bending the language a bit.
- deleted 5y ago[deleted]