A better way to doing if statements in javascript
HTML-код
- Опубликовано: 27 авг 2024
- Instead of using a large if statement block to set a variable, try using a lookup map instead in javascript.
#shorts
------------
🤑 Patreon / webdevjunkie
🔔 Newsletter eepurl.com/hnderP
💬 Discord / discord
📁. GitHub github.com/cod...
beware that objects created with object literals inherit properties from Object.prototype . that means that if day is 'toString', then values[day] will actually return a function and not a numerical value as you expect
An “easy” solution is to use a null-prototype object:
const lookupTable = Object.assign(Object.create(null), { monday: 1, tuesday: 2, … });
Or guard the lookup with:
Object.hasOwn(lookupMap, day)
That being said, this kinda reminds me of the pythonic alternative to switch statements. In this example, I think switch is less edge-case prone and IMO easier to read.
switch (day) {
case “monday”: return 1;
case “tuesday”: return 2;
…
default: return -1;
}
@@reprC an even better solution is not to use such bad language as javascript.
@@tooru chill, why the hate
@@tooru I agree, we should use the other language that's available on the web... Oh wait 😱
@@reprC a better solution than Object.create(null) would be
new Map().set('monday', 0) // ...
Then use the method Map.prototype.get() with the coalesce operator to achieve the same result.
The easiest way to do it would probably be the object literal as demonstrated, using a destructuring assignment, and then checking the value retrieved is the correct type.
const dow = { monday: 0, tuesday: 1... };
const {[day]: value = -1} = dow;
return typeof value === 'number' ? value : -1;
The beauty of Python is that you learn these things at the very beginning, because in python this approach is taken for granted. That's my experience.
This is an interesting approach not just for JavaScript. Maps are everywhere. Thanks for sharing.
map yn = {{"yes",'y'},{"absolutely!",'a'}};
my favorite usecase of map is for command line parsing in cpp!
Wow, you "invented" the dictionary. Great job!
You can name it after me 😂
@@WebDevCody GOATED response💀
they do things i did in delphi 10 years ago...
He’s literally telling people how to do things????????? Like he didn’t say “I invented this” 😂
Nice, I too prefer this method. Howell, in the case of numerical keyed data, the array is a much better fit paired with an indexOf or findIndex
If the data is numerically keyed why would you need indexOf / findIndex?
@@hawkmne In the case where your array is
["Sunday", "Monday", "Tuesday]
and you need to convert your day of the week to a number.
@@AnyVideo999 in that case, using findIndex/indexOf is much slower because lookup time complexity is O(n) compared to using a map/object with constant O(1) lookup time complexity, so no, array is a much worse fit here.
@@hawkmne For surprisingly large values of n, linear search is faster than a hash map. The purpose I opted for an array is that it removes any error prone behaviour when numbering, especially useful in small toy examples like this I'd say. By all means, you can take the entries of the array and make a hash map if you'd prefer.
@@AnyVideo999 it is true for very small values of n, not really for 'surprisingly large' values (though it's not clear what order of magnitude you imply here). In this particular case, linear search might be negligibly faster or equally fast, but generally hashmap lookup is much quicker, even for 'n' values as low as ~50-100, according to my benchmark (using Map, not plain object)
Arrays' indexes left the chat
That's what I always try to do if want to pair objects with consecutive numbers. Just store them in an array and use their indices. This works even if the numbers don't start at zero, as you can simply subtract the lookup number from the smallest number to get the index.
Not sure about JS, but in python dictionaries have O(1) lookup time due to their keys being hashed, compared to O(n) to index an item in a list. So, it will be significantly faster to use a dictionary for this kind of operation (though of course negligible if you just have a handful of key-value pairs)
@@alimanski7941 i can understand that, but honestly if you need speed, just don’t use python 😅
@@lucasgrd4258 just because python (or js, or any other language) isn't the fastest, doesn't mean you get to neglect optimizations. Some optimizing principles are relevant for any language. If you design an entire system in python, you're not going to switch to another language just because you found out you need to index a value in a list of size 10 million.
@@lucasgrd4258 Python will be coming out with an update in the near future that the developers say will increase the speed up to 3x, making it comparable to C and Java. So when that happens this will be outdated.
That said, computers are so fast nowadays that Python's difference in speed is negligible for user programs.
In this case I will use an array with string + indexOf
Good tip. If you need to do anything more than this with maps, use the Map type.
const values = ['tuesday', 'monday', 'wednesday']
values.indexOf('tuesday') // return 0
values.indexOf('sunday') // return -1 becausa not exist
This was my train of thought
have used this so many times.... very useful
switch-case works great here as well. Switch only evaluates once, while if-else evaluates for every condition set...and you don't have to store anything. Best performance as well as storage utilization.
Everyone commenting saying "I would just indexOf()... array... List...etc" doesn't understand that this is incredibly useful for data that is non continuous and works for reference types as well. The only reason this works is because Mon-Sun is linearly mapped to 0-7.
Im a C# dev and we call them dictionaries instead of maps but essentially they are a collection of key->value pairs, where the values could even be generic in type. The last implementation I used this for was in a 'inventory' system (game dev). I can't recall why I needed a dictionary instead of just a list, but they are incredibly useful structures for representing data in all sorts of ways.
When dealing with arbitrary data, it's better to use an actual `Map` than an object, for the same reason the top comment mentioned (prototype collision). Or just use an Object stripped off its prototype
But dont forget to treeshake your js, using Map is good but not so good if you're not utilizing every methods of that class, that comes in tree shaking procedure in node. Esbuild/Vite is built with this.
@@dc22199x WDYM? Map isn't a 3rd party library, it's included in ECMAscript. Do you mean the polyfill? Because yes, adding the entire polyfill is inefficient
When you do it in typescript and define its type like Record you can even save the fallback value since typescript will prevent you to pass in any possible value other than Day (which you would have to define as a literal chain as well like "type Day = 'monday' | 'tuesday'..."
My approach would be using switch
Switch is nice to read but very slow for some reason.
@@melonenlord2723 for real?
Cos I like switch for these kinda stuff
@@melonenlord2723 You shouldnt be concerning yourself for those miniscule performance boosts. You are writing code for people not machines.
Im not native to JS, but I think we can assume that the compiler/interpreter is smart enough, to handle both nearly at the same efficiency.
In Java a big switch statment gets converted to an Hashmap for those values. This brings me back to my first point write code for people not machines.
@@Schnorzel1337 Ok, i tested it again, it doesn't seem to have any difference now. I rememver around some time ago switch was slow for some reason.
switch is terrible
nice, looks like I'm not the only one who prefers this strategy myself over ifs and switches.
Or you could literary use Map followed by nullish coalescing ...
days = new Map([...])
days.get(day) ?? -1
Yea this is way better. The solution shown in video was how we did it before 2015...
I prefer the way he did it in the video for this kind of stuff cuz it’s a lot cleaner:
{ x: 1, y: 2, z: 3 }
new Map([[‘x’, 1], [‘y’, 2], [‘z’, 3]])
One line:
return [“monday”,”…].IndexOf(day);
Tank you! I scrolled way too far for this.
nobody said that the numeric values will corespond to the index
Who said Monday-> Sunday corresponded to 0->6? This way with a object is more generalised. Yours is very specific and wasn’t what was implied here
Isn't this an allocation each time?
That's not the same. It will return 0 for Monday
A different approach would be an Array and just find the index
this would only work if each day mapped to different numbers no?
Sorry i am new to programming so tell me if I am wrong but isn’t he not just describing a dictionary with the key value pairs?
@@bakwertgeek2544 pretty much like that yeah
@@bakwertgeek2544 you learning python right now?
@@emmanuelu yeah learning python right now but why u asking :) ?
For a string mapping, I usually do things like
const childTheme = {
white: ‘black’,
…
}[parentTheme]
By setting parentTheme default to ‘white’, the default for childTheme will always be ‘black’.
I like this approach, had forgotten about this method
as js professional, i can cofirm this is what i do all the time, please do this folks
but keep in mind about accessing property of null it can crash on run time
in this video, he use bracket notation rather than dot notation, it makes difference
const arr = ['monday',….]
const day = arr.indexOf('monday')
Yep. Way better
@@ESArnau but it's slower
@@farhanaditya2647 But in general more useful, and that could makeup in speed, instead of making both, you know?
This is great. Newbie here got to know something new today thanks
or just use switch case statements which is just as readable as if else statements. using dictionary/array for this purpose can be less readable
A daynumver function containing a case whiich responds i agree would be good here
I naturally started using maps/dicts very frequently as I started learning JavaScript for my job. They just make sense to use in so many contexts.
I swear you can always predict exactly what they're going to say.
He had us in the first half.
This indexing principle should be used especially when you want to have lookups in loops. I see junior developers excessively make use of array functions like Filter, map, some etc creating ridiculous amounts of nested loops instead of creating indexes, allowing for Direct property access to a desired entry
I am really enjoying your js shorts.
it'd be better to use an array of strings since the numerical days are within a range 0-6. And also an actual Map would be better than a plain object
I've used this a couple of times, it's very clean and readable, it's a lot faster than if's and just barely slower than switch
How do people know how fast one conditional is relative to another?
Just make an array and use indexOf. Even simpler.
On a practical scenario where any future keys are added, a dictionary is much more easy to add and get rather than using an array.
this is called a jump table and its nice but not for everything
Isn't a hash table?
what would you consider is a bad use case of this?
In this case, you can use an array instead and use `indexOf`, but I really like to avoid if statements using objects, nice tip!
Enums are pretty good for this. That way you can check for a value like so:
Enum.Monday -> 1 or Enum[1] -> 'Monday'
No enums in javascript though.
const day = 'tuesday'
const values = {
monday: 0,
tuesday: 1,
wednesday: 2
}[day]
console.log(day);
little bit simpler :)
I would just use a switch statement. Very clear and does the same thing without creating an object.
Indeed these sorts of related constant strings need to be in const struct and/or in an array.
But when you need to match strings use a regex match.
var day = “Monday”
var pattern = /Monday|Tuesday|Wednesday/;
If ( pattern.test(day) ) {
return “also non-working days!”;
}
Better placed. I use optional chain between object and property and use logical OR as a false statement. Or value in object works too
I will use arrays for my approach, make an array for days and index them from 0, if the days value not in days array will return -1
Another one that I like is immediately invoked anonymous functions. Rather than setting a variable within an if statement, you can return that value from the function. Naturally this lends itself to allow more complex logic within the function as well.
For this specific use case, you put day strings into an array and use .indexOf
Put days in an array and use the index for the number.
Lists left the chat
the easiest option )) = ['понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота', 'воскресенье'].indexOf(day)
1) Use Map if you need a map, stop using objects everywhere
2) On small scale array lookup might be faster due to how slow hash function can be (microbenchmark it to your hearts content)
3) do not recreate lookup maps or arrays inside function if you can prepare them globally. memory allocation is not cheap
4) there's nothing wrong with if or switch statements, do not replace every if/switch statement with map/array lookup.
Why not use switch case?
Would definitely be best to use the Map object now, deep that you can actually get a list of all your keys and many other important prototype features.
Or you could put days in array and use the indexOf method. Would be even more concise
That's O(n) time complexity whereas a map is O(1)
@@YeetYeetYe we’re talking about an array with seven items, c’mon man 😜
That JavaScript functionality reminds me of the Python dictionary
Fr
I did the same in Python
Or
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
let day = days.indexOf('Wed');
And `indexOf` will give you back -1 if it's not in the array.
Thank you for providing this helpful tip
I am so glad this wasn't just another ternary operator clip. I use this kind of thing all the time. Makes future extensibility much more natural as well. Also fits nicely with other good programming practices such as using constants, enums, and configs.
U can place all the strings in array and findIndex() will do the job
Just use a switch-cacse, it uses hashmap under the hood.
switch statements absolutely do _not_ use hashmaps under the hood.
@@DeusGladiorum it absolutely uses hashing/lookups. Do you have evidence to prove otherwise?
@@hellowill Hash maps and hashing are different things
@@oculusquest6703 it's essentially the same thing.
If you want to correct my comment why not just do that instead of saying its completely wrong? Cause it sounded like you think it behaves like an IF statement.
@@hellowill Just to note, you’re talking to a couple different guys. But actually you’re right, I did think it acted like if-statements. Looked it up years ago and I guess the fall-through behavior without break made me believe such. So just never used it in my code lol. But I get mixed results as to whether or not it acts like a true lookup table/hash map though. Like anything else under the hood in JS, it really depends, but it can definitely operate as one.
Or just use typescript and make use of enumerators 😃
Absolutely
Yes enumerators are godly and efficient. This doesn't work for user input string though, does it?
I am a C# student, so i would use enums :)
These shorts are so helpful. Keep them coming.
Have been using this for over a year, if not mistaken, its called as Object Lookup
Yeah lookup table, a map, dictionary, key value store, enum if js had enums. All basically the same name for what this is
You are amazing never knew about dictionaries. That is great. And not to forget '??' does not indicate a fallback function. It a nullish coalescing operator.
If this is inside a function, where is it best to define the object mapping?
- Simply inside the function? Wouldn't that get "redefined" everytime the function is called?
- As a parameter? That would help with the "redefining" thing I feel that's a bit clunky?
- Outside the function? That'd probably be best but then the details kinda go out of scope?
Don't get me wrong, I absolutely do this as well. But there are times I don't know where to put the object definition that I just fallback to if-else statements lol
If I'm remembering things correctly, for literals like that (where the data is defined ahead of time), the compiler/interpreter will preload it into a memory location, and reference it that way, so it is not redefined on each function call
Supporting comments here always broaden my knowledge just as in my expectation
I thought you were going to say the switch statement. Pretty cool
I almost never use switch statements, I don't find them useful.
Whoa, a real eye opener, thanks! Do you know if it's possible to store multiple strings or values in a single variable??
In this case I would just make a list and use indexOf(), even shorter.
Since Date.getMonth() returns an index you can also avoid if-else by making a simple array:
let months = ['January', 'February', ...]
Gotta say switch statement would be more readable in this particular case
Since this example only uses numbers, you could do an array with indexOf. But this is faster and probably more readable
Enums laughing in the corners
Using objects increases the space complexity. So just use an array and return array[i+1]
Ok so when I started coding professionally I used to do this for situations where there were many conditions I had to handle.
Upon getting my code reviewed, a senior mentioned to me that while it might look “cleaner”, it might not always be the best option.
When writing production code that’s going to be around for years and handled by dozens of devs, you always want to be as explicit as possible lest your intentions be misinterpreted, you also want to reduce the time between your code being initially seen and your code being fully understood.
Using objects or maps can potentially run foul of these 2 things, depending on where the map is defined and if the value is pulled via a function or inline.
It’s always going to be much clearer and explicit to use a switch statement, yes it might not look “cleaner” but these are the situations it was designed for
Just my 2 ce…pennies?
Yeah I think it depends on the use cases, but if it’s a legit value lookup like in this video, I do not see any need for if or switch. The moment you need to run multiple statements when the day is Sunday, get rid of the map approach and go to if else if else
But readability doesn't have much to do with it though, you can always give it a specific name and use keys that match the name, of course I'm talking about small objects.
Would it be possible to elaborate this example with a video? I get an error message for ?? -1. How does it work? What is the purpose of this code?
This is not "a better way to doing if statements"... this is just a better way to solve this specific problem...
I know you've tried to be generic, but for a M-S
const day = 'Tuesday';
let value = ['Monday', 'Tuesday',...].indexOf(day);
and value will be the correct value or -1.
Yeah, using a long if else statement isn't a good idea. Having a data structure is much better than that.
Thank you and thumbs up 😉👍!
you can also create a list with all the days and then run the .indexOf(day) function on it
That trip is amazing 🤩
Well... I wouldnt use object for that. Javascript Maps were created and intended for this type of case. Especially that they have very easy and straight-forward methods for getting and setting the values :)
Map vs object, literally the same data structure imo
I thought maps were for when the structure of an object changes more than a slight amount?
You could just use an array with your days in and use findindex on it it’s one line
Hashmap, hashmap, hashmap!!! Hashmaps are always the answer
Nice. Cleaned up an ugly switch case with a objectMap
protip: *almost* never do this, instead -- use arrays. The only time you should have objects like this is if you're using them with `.reduce`.
The object returns 0 if the day is Monday in which case days[key] ?? -1 will return -1 as "zero" will be interpreted as" false ".
I think the ?? Only falls back on null and undefined
@@WebDevCody thanks a lot for clarifying that to me ! I just tested it by myself it's working as you said ! And thank you again for clarifying that !
You could freeze the object to prevent future changes
it's people like this that confuse me on stack overflow.
when you see the program code on the forum like 'what is this, how does it function?, why does it work?, what is the logic?"😂
Create an array like ["Monday "] and do Object.keys gets keys should do it as well or getting specific indexOf array location can provide integer.
Why not represent your days as numbers in the first place, with an enumerator or something? Does that exist in JS? That would (very likely) save processing time and memory.
I’m just teaching a concept, I didn’t think everyone would question the example so critically 😅
@@WebDevCody .. it’s the internet, expect the worst 😂
OR
You could save Monday to Sunday in an array and just return its index or index +1 based on requirement and do a nullish cohelscing check and return -1 if the value is not in array….
you could also write an array and use a for loop.
Its like Javascript people never heard of objects before. I mean this is how you would do it in java/C#. Nice that you brought it up here too!
Sometimes it’s just hard for a beginner to know when to use what pattern when solving a problem
try arrays they will blow your mind
Are you and Web Dev Simplified lab clones?
Lol no
Good idea.
Instead use an array
Sure for this example because we happen to return numbers that happen to increment from 0, but what if we didn’t return numbers we’d need to do something like this
okay it make sense now
Keep doing it brother i love this type of videos it really help me
Great job. Which font are you using by the way?
Should be in description I think
@@WebDevCody I just checked. I did not see any mention of a font
@@yeboahnanaosei check out one of my latest videos
@@WebDevCody I'm confused. I wanted to find out the name of the font in this video.
Use ES6 maps instead of plain old objects. Objects weren't designed to be used like this and have some pitfalls as mentioned by others in the comments.
I think it’s fine.
One hacky javascript way to do Enums is like this:
function createEnum(values) {
const enumObject = {};
for (const val of values) {
enumObject[val] = val;
}
return Object.freeze(enumObject);
}
const Days= createEnum(['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Satursday']);
var today = Days.Tuesday;
Yeah, seems a bit hacky, but it would work!
I was using Switch statement but this approach seems better in certain cases.
If the array does not have that elements it will throw an arror. Null coalesce is not sufficient.
Wtf doesn't js have a switch expression?
Yes it does.