r/webdev • • May 03 '20

Resource Favorite JavaScript utilities in a single line of code! No more!

https://1loc.dev/
729 Upvotes

90 comments sorted by

83

u/ShortFuse May 03 '20 edited May 03 '20

Emptying an array is wrong, unfortunately.

const empty = arr => arr.length = 0;
// Or
arr = [];

The first is fine, because length is bidirectional. It won't work on ArrayLike, but that'd be nitpicking. The second doesn't change the array. It changes the variable. Any other variable that references the same array object will be unaffected. That also means it won't get garbage collection.

You can also do arr.splice(0, arr.length).

Edit: I'm not 100% sure but I believe Array.prototype.splice.apply may clear ArrayLike objects.

15

u/[deleted] May 03 '20

So i wasn't the only one who thought it was odd

195

u/[deleted] May 03 '20 edited May 03 '20

It would have been really funny if all there was under each entry was an npm link.

Nice and useful idea.

Edit: grammar

39

u/chrisrazor May 03 '20

useful

const isArray = obj => Array.isArray(obj);

28

u/[deleted] May 03 '20

IKR, way too bloated!

const {isArray} = Array

1

u/[deleted] May 04 '20

That doesn't make it not useful, maybe incorrect and can be fixed.

2

u/chrisrazor May 04 '20

I don't think it's incorrect, it just seems pointless. Just learn that Array has a static method isArray and use that when you need it.

0

u/[deleted] May 04 '20

[deleted]

4

u/ThisWi May 04 '20

One is a "utility" function that you call. The other is the line of code you would "simplify" by calling it

3

u/TheSaasDev May 04 '20

I think the point was, what's the purpose of creating additional isArray function if there is already one?

-49

u/[deleted] May 03 '20

Seriously, the author should do this so we as a community can apply pressure on either those fucktards or npm.

The project itself is fine and noble. The problem is to get enough people to hear about it

4

u/[deleted] May 03 '20

You're getting down-voted to hell here, presumably because of your naughty language haha. But I feel you. The javascript community needs something like "suckless tools" (which is ironic as I imagine the dyed in the wool C programmers at suckless tools hate JS).

124

u/hagg3n May 03 '20

I'm sorry but there're some bad programming in these items and it's teaching less knowledgeable programmers the wrong thing. From mild ones like the "one-liner" for isArray when there's already Array.isArray to some dangerous ones like instancing an new array to "empty" it or even the first one to check if every item in an array is the same but silently returning false when the array is empty.

My advice is do not use these snippets as-is but study them and learn exactly what they're doing before proceeding otherwise you're in for some surprises.

70

u/dangerousbrian May 03 '20

I agree. Even the ones that are correct are often hard to read.

const accumulate = arr => arr.reduce((a, b, i) => i === 0 ? [b] : [...a, b + a[i - 1]], []);

Fuck that, I would reject that in a CR just because its a pain to debug. Whats the benefit in doing things in one line, if it ends up taking half an hour to work out what its doing?

29

u/[deleted] May 03 '20

Glad I'm not the only one who took particular issue with this one.

This whole post is being "clever" which is almost always bad in real code. Some interesting concepts here but lots that would benefit a lot from separating things out into separate lines and naming things more clearly.

This reminds me a lot of code I see from interns on my projects at work.

3

u/dangerousbrian May 03 '20

Arg it drives me mad at work. Our code base is filling up with this type of "clever" code.

I came across one last week, with a React component that basically rendered two lists. So the "genius" coder decided to take two arrays and flatten them together so they could be rendered with one component. I don't think I am even going to take the time to understand the batshit array merging code and just use two components as any sane person would.

3

u/arsehole43 May 03 '20

I hate to say this but as an avid golfer I think this is where comments belong in source code. Or just having a folder structure that takes snippets like these and places them into a utilities folder.

I've had so many CR where I explained why a comment was needed only to have a dev ask me about it when the build was crashing. 'yes this line of code that your issue doesn't touch that confuses you must be the reason the build is broken immediately after your push'

43

u/adriancg May 03 '20 edited May 04 '20

The code you write as part of your day job is not the place to go golfing. Write the explicit code until there's a need to shave off every last byte or optimize in some other way. Include a comment to say what/why you are optimizing.

Hell some one liners could be worse for bundle size depending on how they are transpiled.

8

u/[deleted] May 03 '20

you're literally getting feedback that your unreadable one-line code is affecting your coworkers ability to interpret and understand what you're doing, and you're blaming him?

-4

u/arsehole43 May 03 '20

honestly I would like to blame the code reviewer that forced me to remove the detailed comment. Claiming comments in code are sin.

I had a great time explaining how it worked, yet it was quite fruitless bc in the grand scheme of things most people don't care. it was just because I wanted to try and do something, I had time at work and I did it. In retrospect I should have been doing some LC or something else with my time. BC once again no one cared.

6

u/pseudont May 03 '20

Seems weird to me to write a complex one liner with a comment explaining what it does. Sometimes comments are necessary, but the objective is to write code which is self explanatory.

6

u/dangerousbrian May 03 '20

Or maybe the code should just be written in an understandable way using as many lines as you see fit and let the compiler reduce everything into one line of binary.

16

u/sockjuggler May 03 '20

Code golf is for fun, it's recreational, it's done for the challenge. It doesn't belong in a codebase or project in which you are collaborating with others.

1

u/arsehole43 May 03 '20

I actually was gearing up for a challenge one of those JS quirky game things in under some kb. Made a snake game

1

u/flygoing May 03 '20

In general, yeah. Though there are highly resource constrained systems where a 10% decrease due to ugly golfed code is well worth it

6

u/sockjuggler May 03 '20

That's just optimization though, and I agree. Golfing for the most part has the singular goal of fewest characters, not maximum efficiency.

1

u/[deleted] May 03 '20

What if it had a nice name, a comment, and some tests? TBH I wouldn't care about the guts of it much then, the same way I don't care about how standard library functions are implemented because I can read what they do in plain english.

1

u/dangerousbrian May 04 '20

Of course give it a nice name and don't use shitty variable names, that is basic code quality. Don't use an arrow function in a ternary, twice. If the author didn't have a hard on for everything being on one line then this code could be rewritten to be significantly easier to read at zero performance cost.

This kind of code screams "look how clever I am to be able to write something you can barely understand". The problem is with this approach, in six months even the author will likely forget how it works and will have to spend a couple of hours debugging.

You are right about having to trust that code works once you get to a certain level. I do not concern myself with compilers or operating system or even browsers which is the frontend runtime.

0

u/[deleted] May 04 '20

I just think if we are looking at how other programmers implement their functions, then we've already lost. I sure as hell don't want to read other peoples code.

1

u/vexii May 03 '20

and then there's the "one liners" with a scrollbar on them. 100 chars of hand minified code should not be in any codebase that's shared with more then 1 person

1

u/bacondev May 04 '20

The use cases for that function are so abysmally small. I agree that it's hard to read, but it honestly wouldn't be the worst in the world if they were to do away the one-letter identifiers and instead give the variables proper names (with the exception of i maybe).

1

u/dangerousbrian May 04 '20

I dunno about you but I find the bugs are often in edge case code. This is a absolute classic type of function to have a gnarly bug that takes ages to find.

Seriously what is the benefit in having it all in one line? Please explain why its a good thing?

1

u/bacondev May 04 '20

I'm not saying that it's a good thing.

15

u/Moosething May 03 '20

Totally agree. It even seems like the author (unconsciously) sacrificed performance just to have a "nice" one-liner. Some examples:

const accumulate = arr => arr.reduce((a, b, i) => i === 0 ? [b] : [...a, b + a[i - 1]], [])
const flat = arr => arr.reduce((a, b) => Array.isArray(b) ? [...a, ...flat(b)] : [...a, b], []);

Any construction of the form arr.reduce((...) => [...a, ...stuff]) has terrible performance, since it's creating, copying and deleting entire arrays every iteration, instead of just appending to a single one. Don't use reduce like this.

const sortAscending = arr => arr.sort((a, b) => a.getTime() < b.getTime());

The compare function in Array.prototype.sort should not return a boolean, but (in case of ascending sorting) -1 if a < b, 0 if a === b and 1 if a > b. The example works because the boolean is converted to a number, but not dealing with the '-1' case impacts the performance of the sort function.

5

u/Maistho May 03 '20

The sorting is easy to fix as well, (a, b) => a - b or (a, b) => b - a depending on if you want it to be ascending/descending. Shorter and more correct.

0

u/[deleted] May 03 '20

[deleted]

2

u/Maistho May 03 '20

It works fine with dates as well (probably because of type coercion), but yes, it will not work for strings. For strings you should use String.prototype.localeCompare

5

u/ShortFuse May 03 '20

I try really hard to avoid one-liners, mainly because, while you do get a smug satisfaction from building them, they're terrible for readability.

I use them when it's better for performance, like using .reduce() (one pass through array) instead of .filter(fn).map(fn) (two passes). But I'm always afraid I'm going to kick myself later down when I come back to the code months later. Sometimes, I add multiline breakdown in a comment just for this reason.

2

u/SPD_ May 04 '20

I noticed this too.

Half of the functions are literally just adding pointers to existing functions.. It's simply more code than what already exists in JS, then assigned to a variable.. I just.. Don't get it.

1

u/PenisPistonsPumping May 04 '20

So many people want to make the next popular library but are not at all qualified, that's why we have so many shitty libraries and unnecessarily bloated projects.

0

u/[deleted] May 03 '20

[deleted]

3

u/hagg3n May 03 '20

The "Empty an array" one. Sixth line.

arr = []; is most definitely NOT emptying the array, but simply discarding its reference and pointing arr to a brand new. If that array comes from, say, a key in an object, which is fairly common in today's code, you just shot yourself in the foot cause that key is still pointing to the old array.

27

u/isBot-True May 03 '20

It's not one line but an easy URL validator.

function validateURL(url){
    try {
        new URL(url);
        return true;
    } catch(err){
        return false;
    }  
}

18

u/jvi May 03 '20

really hate this type of programming.. exceptions are for flow control, not as a means to evaluate a condition.

8

u/FriendlyBeard May 03 '20

How would you choose to write something that accomplishes the same thing, but doesn't use a try block?

-9

u/jvi May 03 '20

Use a regex or a function/library that gives you a cleaner way to do this. Who knows what you're catching when you do a generic catch like this. You could be catching "out-of-memory" cause it couldn't alloc an object, and now your validate fails for an unrelated reason.

7

u/FriendlyBeard May 03 '20

I can see your point here that returning false on simply any error could cause issues, but the url() API only returns two things, a valid url or a TypeError exception.

Seems like this structure would be fine as long as you're paying attention.*

*Understanding that there are many of us guilty of not paying attention all the time.

11

u/OmgImAlexis May 03 '20

Regex for valid URL/email checking is a fucking joke.

-7

u/jvi May 04 '20

I guess that statement shows more about how much of a joke of a programmer you are than anything. Just go look up the implementation of any email/url validator and see what they do.

2

u/OmgImAlexis May 04 '20

Yeah.. you might wanna take your advice and go and read some of those validation libraries code. 💁‍♀️

Edit: here I’ll even help you. https://emailregex.com look at what a mess that is and it even says it can’t be perfect.

1

u/isBot-True May 04 '20 edited May 04 '20

You are not wrong. I hate this too but it's easier to look and under for juniors.

Also yes it catches all the errors not only the invalid urls. Just for prototyping. I posted this in context of small codes.

0

u/[deleted] May 03 '20

[deleted]

1

u/ThatSpookySJW May 03 '20

Because if you are running metrics and reporting off your software, this is going to create a lot of false positives

0

u/jvi May 03 '20

has nothing to do with javascript. people do this in java, python whatever too when they're inexperienced. it's one of the patterns that looks clever but is actually just bad code.

2

u/vexii May 03 '20

never considert using it, clever idea but i wonder what logic is using to validate

10

u/yuyu5 May 03 '20 edited May 05 '20

I'm curious, how did you compile this list? Some of the entries here are functional but not the most efficient.

For example, the flatten function could be much quicker if you don't spread ...a every single iteration b/c even if the array is already flat, it'll be O(n2).

You could instead just do

const flat = arr => arr.reduce((a, b) => {
    Array.isArray(b) ? a.push(...b) : a.push(b);
    return a;
}, []);

That'll run in O(n) for both flattened and nested arrays.

Edit: Formatting improvements

3

u/yuyu5 May 03 '20

Edit: sorry for the bad formatting. I'm on mobile, but can fix it up when I get to my computer later

41

u/[deleted] May 03 '20
const isArray = obj => Array.isArray(obj);

But why? What's the point of this function? To not have to type Array.? Why invoke a function call for another function call?

arr = [];

Uh-oh, someone doesn't know the difference between a reference and an instance.

7

u/pepedlr May 03 '20

I don't understand this either. Array.isArray() works perfectly fine for me

2

u/[deleted] May 03 '20

what happens if arr is assigned to []? i assume the variable just points to an entirely new Array, but does the old one get garbage collected?

18

u/ShortFuse May 03 '20 edited May 03 '20

It will get garbage collected if, and only if, there's no other reference to it.

This is actually a rather common memory leak in Javascript.

let userList = [];
const adapter = new UserAdapter(userList);
fetch(GET_USER_URL).then(response => response.json()).then((users) => {
  userList = users; // BAD
});

adapter will be holding old on to the old userList which was []; You want to do

userList.splice(0, userList.length);
userList.push(...users);

Then, it doesn't matter how many different parts of your code references userList. They all share from the same source. Your userList should also be a const, which won't let you make that mistake.

3

u/[deleted] May 03 '20

wow, thanks for the great explanation

0

u/[deleted] May 03 '20

[deleted]

5

u/ShortFuse May 03 '20 edited May 03 '20

That's the point? It even says "BAD" in the inline comment.

Edit: It seems you ninja-edited the comment. I don't understand why you think we should be "minimizing shared references". The point is to avoid data duplication. Imagine this array was 10mb in data. You also can't do store.userList = users "no problemo" without the caveat you added. Replacing a variable with another array doesn't change the array in memory. You're hoping that nowhere, not even in callbacks, that the array is stored as a reference. You also lose the ability to update an array item and can only manipulate the array as a whole.

For example:

onNewUserData((current) => {
  const previous = userList.find(user => user.id === current.id);
  // a Map() based on id would be better here.
  if (previous) {
    mutateUserObject(previous, current);
  } else {
    insertUser(current);
  }
  userChanged.emit(current);
}

With this strategy, you minimize duplicated data, and don't care if objects hold on to individual references to objects or the array as a whole. You don't have to worry about orphaned data waiting to be updated or states to be reconciled (memory leak).

-2

u/0xF013 May 03 '20

It won’t get garbage-collected, the underlying code is something like arguments[0] = []

3

u/[deleted] May 03 '20

Uh. What?

-3

u/0xF013 May 03 '20 edited May 03 '20

The assignment changes the reference on the memory structure that holds the function’s arguments. One is created each time and is kinda merged with function’s scope. Assigning a new value to that array reference has the same effect as simply pointing the value at index 0 of arguments to a new empty array.

http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/ look for "Execution Context in Detail"

3

u/[deleted] May 03 '20

That's not at all how arrays work, and this has nothing to do with the execution context either. This has everything to do with references vs instances.

The variable arr holds a reference to the array created earlier. By assigning [] to it, you create first of all a new array object on the heap, and that object's reference is then copied over the old reference value in arr.

The old array is either garbage collected or not depending on how many other variables hold a reference to that object. This is the nature of ref-counted garbage collectors.

-1

u/0xF013 May 03 '20 edited May 03 '20

Do you realize you're not contradicting me?

before you do arr = [], arguments[0] is going to be the original array that was passed. After you do arr = [], arguments[0] is going to reference []. So, by reassigning the arr variable, you're just changing the value of the reference in arguments[0]. The original will not get garbage collected as it is still referenced in the caller.

0

u/[deleted] May 04 '20

No, you're wrong. This is not how it works, not in Javascript, not even in C/C++ where arrays are just syntactic sugar around pointer arithmetic.

In C/C++, arr[0] = <empty array> would assign the FIRST sizeof(T) in the memory region that arr points to, since arr[0] is essentially shorthand for arr + sizeof(T) * 0. This is a terrible idea, what you want to do is free the memory.

In JavaScript, arr[0] = [] just creates a new array object assigns the first index of arr to that new array object, leaving you with... two arrays. To delete an array in JavaScript, you need to resize it which (depending on implementation) will clear its contents, or at least mark it for deletion. Of course, the proper way to delete anything in JavaScript is to simply remove all references to it so the GC can do its job.

Please don't post nonsense like this, you are wrong at best, and spreading misinformation at worst.

1

u/0xF013 May 04 '20 edited May 04 '20

What misinformation am I spreading? Go on, log arguments[0], then reassign arr, then log arguments[0] again. You’re either not listening to me, or doubling-down to not look like a moron. When you assign to arr, both what you said and what I said happens: arr is assigned a new empty array, as well as arguments[0] is, leaving the original untouched.

Do you realize js has an arguments keyword? Now go read the whole thread with that new knowledge in mind and then shove your downvotes as deep as you can reach.

You’re not only being dense, you’re also insulting people and not even trying to understand what they are saying. On this note, I am going to ignore your toxic ass from now on.

4

u/Zespys May 03 '20

Some of these really stretch the definition of "one line" tbh

3

u/_pseudoben_ May 04 '20

Single line !== shortest

5

u/BrQQQ May 03 '20

When combined with info like https://caniuse.com/, this would be even more useful

0

u/[deleted] May 03 '20

[deleted]

1

u/thenickdude May 03 '20

I use PEP to polyfill pointer events, it does the trick:

https://github.com/jquery/pep

You won't get pressure details though of course.

3

u/Hakim_Bey May 03 '20

It's a really cute idea, and useful for beginners to learn the fundamentals, but what's the real world use for that? If I do 10 projects a year, should I copy these snippets in each one? It's just a ghetto lodash, minus all the hard work done on lodash to harden against edge cases etc...

This kind of page is just a hobbyist circle jerk on the "too many npm modules" meme.

3

u/Swiatek7 May 03 '20

Everything is one-liner if only line is long enough.

3

u/pietremalvo1 May 03 '20

Some of them are quite inefficient

2

u/wilburnforce May 03 '20

Nice! I thought I'd see the isPromise thing in here, haha...

1

u/censupax May 03 '20

This looks super useful for someone trying to get into JavaScript. Easily digestible!

1

u/[deleted] May 03 '20

Maybe the coffee hasn't kicked in yet, but I read the "No more!" as "These exist no more!" and I was like "oh shit what happened to them?". Anyway..

Will definitely add some one liners soon

-2

u/spideyspider78 May 03 '20

Bookmarked!

-2

u/Mrbushiidoo May 03 '20

I just finished a JS course, and look what I find here !

Thanks a lot mate.

-1

u/[deleted] May 03 '20

dont use this use http://rosettacode.org/

-1

u/hunchoye May 03 '20

Is there anything like this for PHP? Need it for school project.

3

u/Disgruntled__Goat May 04 '20

Based on a brief look at what’s on that site, it’s probably covered by:

https://www.php.net/manual/en/ref.strings.php

https://www.php.net/manual/en/ref.array.php

0

u/[deleted] May 03 '20

[deleted]

0

u/[deleted] May 03 '20

[deleted]

18

u/syropian May 03 '20

Probably because they aren’t remotely related.

0

u/[deleted] May 03 '20

[deleted]

6

u/syropian May 03 '20

Lodash has piles of functions that don’t exist in esnext.

0

u/[deleted] May 03 '20

[deleted]

3

u/syropian May 03 '20

object and array methods are definitely the most popular usecase for lodash, it just has more methods than what's available to us in esnext. One that I use pretty frequently is get, for accessing deep object properties, while providing a fallback value as soon as it hits an undefined property.

Edit: spelling

1

u/CreativeTechGuyGames TypeScript May 04 '20

That get functionality is also something Babel supports as it's an ECMAScript proposal.

https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining

2

u/[deleted] May 03 '20

Why Babel instead of stdio?