JavaScript Is Weird (EXTREME EDITION)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Honestly most of the JS type conversions kinda make sense if you squint at it. Like number to string? Sure, Java does that too. String to number? A little weird, but okay.

The big big one that is truly wtf is how reserved words become string versions of themselves. undefined + "" should not be "undefined". I can't think of a single justification for this. I suppose it stems from Lisp's whole concept of symbols but it's totally pointless since there's no real macro system or homoiconicity, and therefore no real metaprogramming in JS.

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/hardwaregeek πŸ“…οΈŽ︎ Aug 23 2019 πŸ—«︎ replies

My takeaway is that I really don't want to ever write javascript and I really like strongly typed languages.

πŸ‘οΈŽ︎ 32 πŸ‘€οΈŽ︎ u/[deleted] πŸ“…οΈŽ︎ Aug 23 2019 πŸ—«︎ replies

He's speaking the language of the gods Satan.

πŸ‘οΈŽ︎ 5 πŸ‘€οΈŽ︎ u/qsdf321 πŸ“…οΈŽ︎ Aug 23 2019 πŸ—«︎ replies

string literals are great fun

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/stalkedbyamoose πŸ“…οΈŽ︎ Aug 23 2019 πŸ—«︎ replies
πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/T567U18 πŸ“…οΈŽ︎ Aug 23 2019 πŸ—«︎ replies
Captions
hello and welcome to low-level JavaScript today we're gonna be talking about the biggest reason that people say the javascript is weird which is implicit type coercion now at least once a year there's a new wave of sort of JavaScript is weird posts that circle the internet and they always use type coercion in some weird-looking way to produce an unexpected result which produces the unusual string banana now this is a toy example of how far this type coercion idea can actually be taken and in today's episode we're going to go to an extreme our disclaimer it goes without saying that you should absolutely not write code like this in a professional environment but that doesn't mean that you shouldn't be able to understand it and explore it so with all of that in mind let's continue so what if I told you that you can write completely valid JavaScript that could do anything but only uses the following characters not only that but we can easily write a compiler that takes regular JavaScript and turns it into this weird version in something like 45 lines of code or so well that's exactly what we're going to do here today so the basic idea here is really simple JavaScript only has a few basic types like strings numbers boolean or razΓ³n objects among some others when you try to do things like adding two different types together javascript uses some rules that it has at the core of the language to decide how it's going to coerce one or of those types into it into the other type so that it can actually add them together so if I try to add a string to a number the number is going to get coerced into a string if I try and add a number to a boolean the boolean is going to get coerced into a number and we can see that we can take the number two and add it to the boolean value true which will give us the number three because true is coerced into the number one whereas false will be coerced into the number zero so you can also use addition or subtraction with an expression to just cause the one thing into a number if we have just plus with an array that's actually going to give us zero this is called a unary expression because we only have one thing acting on by the plus if we were to use a boolean value instead like plus true we would see it turn into a one so we can kind of transform one kind of value into another so the banana example did you see all over the internet which is something a little bit more like this we have the string B plus a and then plus and then a space plus and then a plus a and then we do a to lowercase on that we should see this come out with the string banana and that is because what are we trying to do here that the root of it is that we're trying to take the character a and convert it into a number with the unary plus which of course is going to result in not a number because a is not a number and cannot be sensibly transformed into a number and if you to lowercase that you'll get the middle part of the string and if we look at what it was before you'll see that this is really this so what we're actually doing is saying B plus a plus not a number plus a lowercase it's actually fairly simple this is the set of basic things that we're going to use in order to do something way cooler so first of all let's figure out how we can get numbers we've already seen that we can get a number zero so zero then is just plus empty array now I'm going to store that away in a string so we can reference it later so we need to get to the value plus true but we can't use true because it's not in our list of valid characters what we actually need to do is to get it somehow from from our main type so let's start with an empty array and if we use the exclamation mark will cost that to a boolean that will end up being the value false but we can get it to be true by just using one more exclamation mark which will force it to be true and then we already know that if we just put a plus in front of this will turn that into a number and so now we have the number one again I'm going to wrap that up in a string now how could we get any number well pretty obviously we could we could just sort of keep adding these to each other so let's say we wanted to could take this value and we could add another one of these that would give us the number two and clearly we could do this on until infinity and so let's just write a general way of doing that that's write a function called number is going to take an N and basically all we're going to do is to create an array we can do that with the array dot front we provide a length which is n because we want n elements and then we can use the second argument to say that that should always be the number one and then we join them all together with a plus now we can return that and so let's see if this works the way we expect it to if we want the number seven we should be able to say number seven and we get this kind of expression and if we take that out and we run that here in the debugger we'll see the number seven perfect so now we have a way to get any normal number turned into our strange sequence of characters so now that we have these numbers our goal is going to be to get the following letters by doing these strange operations I'm going to write down here fr om CH a d ET capital s ing small C u P the character space which I'll represent here with the square brackets and we need a backslash now why exactly do we need these characters you might ask well that's going to become clearer as we progress through the journey but by the end if we have these characters we will be able to encode anything in JavaScript so let's get to it the first thing I'm going to do is I'm gonna write an object here I'm going to call it a map we're gonna store all the characters that we collect up in here and the first one we're gonna get is a now we can get a by using the famous northern umber example so there's many ways you can get not a number we can cost a letter to a number but we don't have a in our disposal but what we do have is an object if we run this then we'll see that we get not a number but we actually need a string and a good way and the way we'll use for all of these things to convert something which is not yet a string but we want a string version of it is to simply add an empty array so in the JavaScript code coercion rules that's going to force this thing to be a string and we're going to be able to get the string not a number and strings have the property in JavaScript that you can index them like they're arrays so we can we can provide an index and extract the character of that index so if I wrap this up in parentheses and then we use square brackets the second character in here so the index number one is is the letter A so we can put in here the number one and we should see the letter A but we can't use the number one we need to use our special number encoding so can actually just use number and one but this whole thing we're going to store it as a string because we're gonna want to look back at it later so what I'm going to do is when I put this in the template string we can evaluate the number inside and if we take a look at this we'll see this strange little concoction or just verify that we do indeed get the letter A if we try to add an empty array to an object it's going to force the object to be interpreted as a string and an object when interpreted a string always yields the same result we take an empty object we add an array and we take a look we're going to see the value object object but we can use this to our advantage because this contains quite a lot of the characters need for instance it contains the character Oh it contains e C T the space and so let's just go about extracting these in exactly the same way we did perform you let's check all the first and a nice shortcut this is evil which will let us just run this as code these strings so if we have o we have B of e C T and space all right the boolean true and false are also a nice source of characters we know we can get a boolean there's an exclamation mark square brackets and then we can add another empty array to cast that to a string that's going to give us the string false and from there we can extract F in the 0th position and we can extract s in the in the third position if it cost us - true then we can get our in the first position and we can get you in the second position now for the letters I and n we can use the special floating-point numerical value infinity infinity can be obtained in many ways but one simple way is just to divide a nonzero number by 0 let's take what we have here we know we can get 1 and we know we can get 0 in this way we should get infinity and then if we add to this an empty array we'll get the string ok and here actually I've just realized there's a small mistake on the F because we're providing 0 in here in this there's no way for us to get 0 from what current function so what we should actually do is to add in a little condition here which says if n is zero then just return 0 ok so we've already gotten a good portion of what we need but in order to get the rest of the characters we're going to need to crank the crazy ratchet a little bit if you're all good at anagrams you might have noticed that the letters we have so far can spell out some words one such word is constructor now all values in JavaScript are technically a kind of object and you can always access properties on them with square bracket syntax the following are quite valid in JavaScript we can actually open up square brackets with a string and see the two string function simply by adding the string in here likewise we can use the constructor function which will provide us back the constructor so how can we use this to our advantage but if we were to use this on a string so we can make a simple string just by adding two empty arrays together then we would now actually be able to write this this word constructor out using our map it might be nice to have a sort of a more convenient way of doing this so what I'm going to do is I'm going to write a function called from string from string is going to take a variable S which we're going to immediately split into an array of characters and then we're going to map each character to be the value inside on map and then we're going to join it all back together with pluses and so this from string if we were to use it and provide the string construct them and then run this piece of code we're going to get quite an elaborate string and I'm going to cut and paste this into the debugger so we can see it what we actually get here is the string constructor and if we take that one step further and we take all of what we just got we add an empty array to it we'll have that as a string where we can extract the large capital s there so let's try that you now there are a couple more constructors that we can abuse in the same way namely the regex constructor we can we can get that to get the letter P and all we have to do is to create a minimal regex something like this and get the function constructor and we should be able to see you now we have one more easy character that we can extract without too much hassle which is the back slash so we have to escape the back slash of course and the way we can get it is to just again create a regular expression but we'll put a backslash in then and in order for this to work because of the way that string escaping works we need to put two backslashes in there because this whole thing is going to get encased in a string and we need that to be two backslashes when we evaluate it so we create the regular expression we add an empty array in order to cost it to a string and then we can look up the index which is simply the number things are about to get tricky that we have left over now I'm not going to be found in this way we're gonna have to get them another way the two string function of numbers is actually quite interesting because it takes an extra argument and that says which base the number that string should eventually be converted to so if we would have the number 170 let's say and we were to divert that through a string by default that's going to be converted in base 10 so we're going to get the string on 70 but if we were to applied a different base say base 2 we're going to get the binary representation of that if we were to use base 16 we would get the hexadecimal representation and the nice thing is that bases which are larger than 10 they begin to use the alphabet in order to index the numbers so we can use that to our advantage since we can now actually make the string to string we can get the letter D by saying that well the would be in a number system D would be the value 14 let's say in hexadecimal oh sorry 13 D would be the value 13 but it would be the value 13 in in any number system that let us get up to a character which would be D so we can actually even say 14 here before we would get a weird result like this so if we can encode this which now we easily can and we can get the letter D and it's quite interesting to see what this comes up with this should just be the letter D and this should be from string rather than form string but this kind of monstrosity is what is output by this but if we run this we should see the letter D papel great how we can get the other three letters this way as one or the other three lowercase letters at least you now to anyone that has used the language of the same name it should come as no surprise that the letter C is going to pose some problems and it's going to force us to do some really weird stuff it requires some lateral thinking and I'm actually gonna leave a moment here to pause perhaps you might want to think about how you might make this work okay if you didn't get it don't worry it's not obvious we're gonna need to access a constructor again and let's build this up piece by piece so we're gonna need a constructor but we're going to need the function constructor so let's just evaluate this in line so we can easily read it and we'll take it away afterwards we can get the function constructor by producing an empty arrow function and then if we wrap that up we use our from string with the constructor string so when we've wrapped all of that up we should see that we have access to the function constructor but this time we don't want to cast it into a string we actually want to call this constructor we want to be able to use the function that this provides to us and if you don't know what the function constructor actually does as a function well what it does is it takes a string that represents some JavaScript code and it it turns that into a function that can be calls that will actually run the code inside it's a lot like eval in that way but in some ways it's it has a little bit more constraint which can be applied to it please don't take that as a testament to its safety it's it's basically still like running untrusted code but it's gonna help us out here what we're gonna be able to do with everything that we've put together from here is we're going to be able to use the string return escape so what we're actually doing here is where we're gonna get a function that when we run it is going to return to us the built-in standard library function escape which just like the name implies performs a string escaping to the ASCII value of certain symbols if we call this function in line and I run this hopefully we will see that we have here the function escape and if we call escape and we pass that a string then we should be able to see an escaped value so what can we escape well what we're gonna escape is the map and then the backslash just the backslash let's run that and see what we get we have an escaped backslash which is the hexadecimal number 5c and it's helpfully capitalized the C for us so we can now take that whole expression and index it as a string and we have a capital C but actually the game is pretty much over now we've got our ultimate escape hatch now what we can do is we can scroll back up to the front string function and before if we had a key that was not in this map then we were just gonna get undefined and that's no good if we have a key that we haven't defined here we should be able to find a way to produce that string so we can say if X is not in map then we want to get the character code of X the numerical encoding of this character and we want to get into the string constructor and we know how to do that we add two empty arrays together we use from string so we do a sort of recursive call here and the string we want to get of course is the constructor this is going to give us the string constructor and on the string constructor we have a static method and that static method is called from char code and then to this we can simply pass our character code but we need to encode it in our strange number system so this is our final output and now we have a way to get every single character that we cannot actually access through some other strange way by using off from child code let's actually see if this works the way it should so I'm going to run here the front string function I'm going to give it a character we definitely don't have capital Z that's going to give us an enormous ridiculous set of characters and let's run eval on that and when we run IVA on that we can see the capital Z so that's it we're pretty much done but we're not quite done because the best we could do now is we could take some JavaScript code in and we could convert it into this strange set of symbols but it would still only be a string how do we get that code to run well of course we already know how to get code to run because we've already done it here for C we need to just use the function constructor so what we're going to do is we're going to write a function called compile that's going to take some code and all we're going to do with that is return a string which will be the function constructor we know how to get that and then we need to call from string just the code and then this is just now a function but we need to run that function so we just immediately call it afterwards let's try this out on something a little bit more complicated will console that log the result of calling compile on a string and in the string let's actually do a consorted log let's say hello world so this is the world's most ridiculous hello world program and it will of course help to not have the letter x there instead of the letter c which this should be let's change to the terminal let's bring this terminal to the bottom and let's run this crazy program it's like looking at some sort of weird matrix this pipe that into a file called output KS and if we open that up and take a look at it my syntax highlighter is going to struggle to try and pass this file oh my gosh so it goes on for pages and pages and there's really there's no sense in there but hopefully if we run this we actually see our message helloworld so now the next time someone shows you a toy example of the banana that's blowing their mind I hope you point them to this video and show them what can really be done if you mess with type coercion big shout out to Martin clapper who is the guy who figured all of this out a few years ago I'm gonna put a link below to his website also the github repository where I'm going to put the code of today's video I hope you've enjoyed this load of a JavaScript video please consider subscribing if you would like to see more cool stuff like this or if you'd like to see some of the more serious things that will be happening on this channel like building virtual machines and compilers and all sorts of crazy things that really we shouldn't be using the JavaScript programming language for thank you very much for watching and I'll see you next time
Info
Channel: Low Level JavaScript
Views: 27,076
Rating: 4.9766474 out of 5
Keywords: javascript, learning javascript, js, how to build a compiler, js is weird, javascript is weird, banana, jsfuck
Id: sRWE5tnaxlI
Channel Id: undefined
Length: 21min 28sec (1288 seconds)
Published: Fri Aug 23 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.