You shouldn't be using filter() for the first()/last() methods. It becomes exponentially slower as the array grows in size. slice(0,n)/slice(-n) are much more efficient and show no significant degradation in performance with larger arrays.
@@sarscov9854 I've been working with JS for years, and I deal with very large arrays (10,000+ elements) on a daily basis. Think, for instance, of a legacy format containing a list of products: that format is converted to JSON for easier handling, and a RESTful API is used by several applications to query products from the list. Obviously, storing those products in a database would be a much better approach but because of various infrastructure restrictions and issues, it cannot be implemented for the time being, so we have to stick with the JSON compromise. That IS a real life scenario. And by the way, striving for better performance is NEVER a bad idea, as long as it doesn't obfuscate the code. Which, in this case, it doesn't because slice() is actually much clearer than filter().
@@sarscov9854 I’ve been working in large tech companies for 15 years, we think about performance every day. You would be laughed at with that attitude.
@@benpaul8172 you're an idiot. I didn't say performance isn't important. Sometimes the juice isn't worth the squeeze. You're probably that guy that holds tickets hostage by not approving PRs for miniscule things and making QA have to work overtime near the end of sprints.
Kyle, great subject. I was worried that it would be one of those "include this now-CVE'd NPM library". Having your own utilities is something some programmers fail utilize nowadays. (Nothing wrong with NPM as a whole, but it has its caveats). Now more importantly, you have a good presentation style, and even though you speak rapidly (this is a plus), your speech is quite clear and understandable. I'm always interested in the content you create, and even if I don't find it useful or maybe is old hack for me I don't feel like I've wasted time hearing what you have to say (in general I usually find I learn something new or at least something new to think about). Keep up the great work.
@@ChaoticNeutralMatt I think his speech speed is brilliant whereas many other RU-vidrs do not have. If they are all same speed, there is no personal preference tho. I come here just to listen to his voice and see his face btw. lol
Thanks to your javascript tutorials I learned how to access all of your video files from your website, so now I can watch them for free and I also uploaded them on torrent so everyone is happy ^^
You are just doing an amazing job man. thanks for sharing your knowledge with the community. I really appreciate you from the bottom of my heart. Thanks a lot.
Man your content is amazing. Been working on a vaniila js project and I have so many utility functions as esm, they are so handy. About to modify some of them to use yours 😂 and add the rest to my huge util.js file. Thanks man. Amazing work.
Awesome video and great advice. Just as every good chef maintains their personal set of knives, every good programmer should have their personal arsenal of general-use utility functions. Your “bag of tricks” should follow you in your travels as a developer and evolve/improve with repeated use across multiple projects. This has the added benefit of making your work more consistent and therefore easier to maintain over time. Nice work, Kyle!
If you're still working with a framework which directly manipulates DOM. Chances are it's JQuery which has easier selector and a much larger feature/function set
What a coincidence. I just searched for js useful common code snippets yesterday. I need a function that picked a random number min~max, random item in array, delay promise, etc. The ones I always have are the shortcut to get element by id and selectors. I need your createElement and addGlobalEventListener now. 😁
I would argue that most of what these functions are trying to achieve are already simple enough to write in vanilla javascript. And as for the global event listeners be very careful with those. It's always better to explicitly add those events the normal way in order to remember to remove them when necessary. I like the create element one though :), nice and clean. Good content
@@solvedfyi while that is true I think he has a point and I agree with some of the utilities shown. E.g. "qs" is nothing different than "...querySelector". It is a replacement of a oneliner with another oneliner. Here I would argue that people who know JS they will instantly understand the .querySelector version since it is the official one. For qs they have to think what do those two characters mean and in worst case look it up to find out that it is basically a different syntax for a oneliner. Utilities IMHO should simplify things and make it easier to read. A great example was the math utility for a random number.
@@solvedfyi they aren't vanilla js anymore at this point. Every new programmer will have to learn every utility what it does and how to use it. jquery uses vanilla js too under the hood.
@@indoom This is not importing a library, like jQuery. The video shows writing the function yourself. Writing functions to reuse throughout your code is still just javascript, it's not a framework
@@Quillraven My understanding of the point of the video is you're writing functions for yourself so you can move more quickly from project to project. You write a qs so that you don't have to write document.querySelector each time, but you know what it is because it's your own code. If a guest is looking at your code is like any other function, it will link to the function definition. This particular example doesn't save that much typing but the overall idea of writing simple functions around complex ones is something I expect we all do. The video wasn't "download this module and use these mystery functions", it was "write this around this to save you time"
2:15 There's no way to unsubscribe from this. Definite subscription leak. Also, e.target.matches is not a good way if there is some content inside. e.target.closest(selector) would be much better. But anyway, the handler will need to request it again. 4:20 Attrs are not always the same as props. So in some cases it can work incorrectly. 6:22 Prefer name `delay` like in C# as `sleep` usually means blocking operation. 8:13 In most cases you don't need generic memoization. See no reasons to have this function. Also, heavy calculations usually based on large amount of data, so JSON.stringify can be expensive too. 9:13 See no reasons to write first(smth) instead of smth[0]. Inconsistent return type (element vs array) is antipattern too. Even if it is usefull, would be better to use undefined for single and 1 for an array. If I need 2 elements of 10000, filter will check them all. Normal array.slice(0, n) wouldn't. And the same qusestion: why use this function instead of standart slice? 9:26 last for single element is more usefull as arr.at(-1) may need polyfill, but for several elements why is it better then arr.slice(-n)? 10:19 No need to spread on newly created objects. Absolutely useless waste of performance. 14:26 It will be inconsistent as different monthes have different number of days and weeks. If create such helper (actually I hate relative dates everywhere), it should work much better and be predictable.
You are correct on every point, but I sense a hostile tone from you 😅 i think he's just making content to get that $ from yt, and hes constantly saying "check my blog" for even more adsense $. But it is perhaps somewhat usefull to people learning, it gives them ideas and encourages them to create their own util f(), and some people work at companies where they dont even use utils, so this is nice to have even if it's not the best of the best
Awesome video, but how would you stack a function, the groupBy for example, suppose you had an array of objects of people like the example, but you wanted to group them by gender, then hair color, then eye color. How would you write something like that? I tried what I thought it would be, but didn't work.
14:23 where you talk about the formatRelativeDate function. I am getting this error in SAFARI Browser -> ~undefined is not an object (evaluating 'division.amount')~ Can anyone help me out with this issue ?
Excellent video. Can you do a video on using the underscore as a variable like you do in first and last array functions. I don't quite understand that.
It's use when a function expects 2 arguments, but you will not reference the first. In this case, Array.filter expects an array item and (optionally) an index. But since only the index will be handled in the function scope, and since it MUST come second, you put an underscore in lieu of the first argument.
Pulluting prototype with custom methors is considered as a bad practice since it can cause some problems with libraries. If it's your hobby projects, sure you can do it but on large codebases when many people are working as a team it's not a good idea.
Is there a reason why you're using `Array.prototype.filter` instead of `Array.prototype.slice` in the `first` function? I see no point in looping through the whole array just to get the first n items.
I find myself having lots of lines that just store the results of `getElementById` and `querySelector` into variables, so I've started using this util function to allow destructuring for much shorter and cleaner code (obvs with proper line breaks and indentation it looks much nicer): function $(...selectors) { return selectors.map(e => { let ret = document.querySelectorAll(e); return ret.length > 0 ? (ret.length === 1 ? ret[0] : ret) : null; }); } So now I can do things like this: const [mainContent, allInputs, bags, messageArea] = $('#mainContent', 'input', '.bag', '#messageArea'); It becomes so easy to add/remove/change any of the elements I'm targeting, and it automatically handles setting the value to the element if there's only one match or the full node list if there is more than one match. It's made my scripts so much cleaner whenever I have DOM manipulation (which I often do when writing smaller pages that aren't important enough to set up a full React app).
I'm wondering that if you write your project using these custom functions, won't it be hard for others to read your code? Like they can't understand what qs means
setTimeOut is asynchronous, which means if you want to execute a bunch of code after the timeout, you'll have to put it all inside one function and call setTimeOut with that function's callback. Using Kyle's sleep function converts it to a Promise, so you can use the *then* and *catch* functions to make it easier, or even the async / await format. TL;DR - They work the same way, but it's easier to use sleep and follow it up with multiple functions, rather than using setTimeOut with one function callback that calls all your other functions in order.
It basically waits some duration and executes. Same thing as timeout, but maybe easier to type/read. Overkill imo, but if you use it often, then it might be useful
Unless you use async/await, there's literally no difference as the promise then/catch syntax is identical to having to use a callback chain in the timeout. So honestly this is just as useless as the "qs" shortcut unless you actually want to make use of the fact that it returns a promise and specifically by using the async/await syntax for clarity (e.g. await sleep(100);)
Is it that much harder to write though? The thing is half the time, you end up adding functionality over functionality to the utilities themselves because you reach more complex cases. If it's genuinely very tough to write (example WebRTC / IndexedDB), please do go ahead and make sure you add as many utils as possible. And if it's a function you use all the time just with different params from the browser API, please do go ahead and modularise it. I would argue that using browser APIs directly would be a better choice if the saving is minimal.
For the array utils, extending them to the array prototype is better than passing it as a function. The "first" function, is just slice, and less optimized because it continues filtering the other elements even it's not necessary (it should stop on the first False check)
I think its never a good idea to add methods to the native prototypes itself if you are going to build something at scale, because at some point of time that could lead to conflicts if JS decides to add that method, and future developers would really have a hard time interpreting that. Please correct me if I am wrong.
@@AmanSingh-px5if You are correct, extending the prototype is dangerous. If you're gonna do it, just be aware of it, and if conflicts arise in the future, the lead dev should know how to react. the only good use-case for this is to enable method chaining, instead of doing composition
Very informative, but I don't agree with the queryselector functions and the create element function. Creating those functions makes the code harder to read. If you want to save time it would be better practice to set a shortcut in Visual Studio Code. That way you still save time but your code remains readable by any new programmer that is gonna touch it. Also, personally I like to put the randomNumberBetween function on the Math class. Because it is a function that uses Math and so you can call it staticly with Math.randomNumberBetween.
I'm really not sure why anyone would even use document.createElement() in 2022 anyway since we have template literals and insertAdjascentHTML(). You could argue performance but I defy you to find a realistic scenario where an actual user could perceive the difference between creating document fragments and nodes vs. just writing an HTML string and using inner/outer HTML or insertAdjascentHTML(). All the if statements he added for those irregular attributes are taken care of since the JS engine will just interpret the HTML string correctly without issue.
I think your groupBy implementation is inefficient, because the spread syntax copies the entire object into a new one (and lets the GB dispose the previous) every single iteration
New developers that are just starting to learn web development will probably learn vanilla JavaScript first, and I'm sure it would be easy to transition into Typescript. This channel is a treasure chest of fundamentals imo Your suggestion is not a bad idea btw
All these functions can be easely changed into typescript. Even pluck. For all other functions see no difficulties at all. function pluck(arr: T[], key: K): T[K][] { return arr.map(x => x[key]); } const arr = [{ id: 1, name: "A", x: 1 }, { id: 2, name: "B", x: "" }] const ids = pluck(arr, "id") // number[] const names = pluck(arr, "name") // string[] const xs = pluck(arr, "x") // (string | number)[] const oops = pluck(arr, "oops") // Argument of type '"oops"' is not assignable to parameter of type '"id" | "name" | "x"'
@@lxdixd prototype manipulation is terrible because you don't get any intellisense or tooling support, you don't know when it's initialised unless you have control, and it might collide with other prototype manipulation (it's global)
@@FunctionGermany true, was curious. I use typescript in vsc so i don't really have to deal with no intellisense since it has intellisense everywhere, but i can see the disadvantages of prototype modification.
No. Do not pollute the standard prototype. MooTools did this, then when features were being added in new versions of JavaScript they had to go use a different awkward name because MooTools already took the good one
no, there's no point in doing that because it doesn't await anything. it creates and returns a promise that a function calling sleep could await however.
Readable code is always more valuable than easy-to-type code. It's criminal to take descriptive functions and rename them to "qs" and "qsa" and that really kind of highlights the one complaint I have about your channel: You've either never worked with other people or have simply never been told "No" on anything. I like some of these concepts but I don't understand this-very incorrect-notion that programming is slow because things take a long time to type. Programming is slow because we are solving problems, not for lack of short function names. Create a reusable library for sure but make it a good one with descriptive names and built-in documentation.
Title is misleading doesn't relate to content very much Wouldn't global event handler have bad performance like some events is triggering contantly like mouse move Last thing why not using slice , it has best performance
Hahaha, I've created similar functions to yours qs & qsa (with exact that naming), and added to GreaseMonkey years ago ;) My qsa() returns array (using Array.from()) that way I can quickly use array methods like map or reduce.