 So as he said, yes, I'm from Atlanta, Georgia. The last snow craze we had was less than an inch, so this is really wild to me. Walking down to a conference, and in the time I walked down, suddenly we have half a foot of snow, completely foreign. So I told myself that I'd never do a mind-blowing style talk because I don't lie, I like to think. I never exaggerate, and I never like to do just one weird thing. But as it is, here I am, here you are, all stuck in the snow, so we're stuck with it. So before we get into the mind-blowing business, let me tell you just a little bit about myself. I'm Jonathan Martin. I work at the Big Nerd Ranch down in Atlanta, Georgia, with our Rails and Frontend Development Department. If you happen to be down in Atlanta at any time, I guarantee we will not have enough snow to prevent you from coming out to visit one of our campuses. So we'd love to have you. So everyone nowadays, when it comes to JavaScript, talks about scopes and closures. But for years, people have survived really well without this memory-intensive complication on top of the JavaScript run time. So to avoid any kind of variable shadowing or name collisions, all you had to do was prefix your global variables with some nice little prefix. Fortran, for example, long predated closures. It was introduced in 1957. That was back when a corrupted punch card really meant that you just got some mustard on the card as opposed to a corrupted memory. So considering we still rely on so many of these super-optimized math algorithms in Fortran, I'd say we did pretty well without closures or local variables or any of that nonsense. Then we had x86 assembly introduced in 1978. In my opinion, this was one of the first real languages because you could totally write hello world and operating systems in it without this notion of local variables or any of that nonsense. People actually used it, and they did pretty well with it. And then we had Ruby introduced in 1995. Now we all know it came as just the last ditch effort to save object-oriented programming from the closure craze that was happening during that time. And thanks to Ruby, Oop lives on very strongly and people still write things with classes instead of closures which are heavily frowned upon by Twitter. So to the point, we don't actually need closures nowadays, but spoiled developers naturally keep demanding more features of their language. Now history tells us JavaScript was invented just as a toy substitute for Pascal developers or something like that. So closures were tacked on for these Pascal devs because they were filling the impending irrelevance coming on with the closure craze. So we got closures in JavaScript. The unfortunate thing is closures are slower than a Java GUI. Now over time, developers have fixed the slowness by rewriting some parts of JavaScript. For example, React's virtual DOM tried to rewrite the DOM because of that we totally have a much faster mechanism we can use, no one uses a DOM anymore. So there's different things we could rewrite to speed things up. So to address the underlying performance problems in JavaScript as a whole, well, what better way to speed up JavaScript than to rewrite the entire underlying local variable mechanism, which is incredibly slow. I will not give a big O because that would take too much time to derive. I can tell you in big O notation how long it would take to derive that. So we're going to address these problems and along the way, we'll try to fix the syntax because I mean, no one remembers the var keyword when they're typing out the code. Unless they have JS hint running with its not-so-subtle proddings. So in the spirit of IE compatibility modes, we're going to develop a polyfill for those closure-bound developers to help them get back the speed of global variables that they know and love from assembly and Fortran back in the day. And it will also help them bridge over and forget all this, they've learned about pure functions and Y-combinator propaganda. Now, there's a few rules. When we write this code that we'll use as polyfill, there's a few rules that our code will need to follow to make this efficient. After all, we're trying to speed up the underlying mechanism. First of all, we may not use the native local variables. We may not use it for assignment. We may not use it for retrieval. And we may not use parameters on our functions at all. So our functions always must have no variables attached to them because after all, we're trying to circumvent the entire local variable mechanism. Second, we cannot attach any data directly to a function. Functions are objects, so a lot of people might do some memoization on that. We're not allowed to do that because that could totally lead to memory bloat, which is, we don't wanna talk about that. That could cause issues. However, there are a few things we are allowed to do. First of all, we are allowed to access one global variable, naturally. Also, we're allowed to use amnesic function bodies. These are not function bodies that have no idea who they are. It's just they don't remember things you tell it. So for example, you may not put things on that function with memoization, and it may not know anything about native local variables. So in other words, our functions are no longer going to be closures. They're just buckets of code. Now, we are also allowed to use shortcut local variables for the purpose of this demo, just to make the code a little easier to read. And with these rules, we can derive something like this. So here are the three things we might do in JavaScript. One is assigning a variable, another retrieving, and another setting up a function to be put in a local variable. We're going to replace these. So for variable assignments, we'll replace it with this mysterious s function, which will take in the name of the variable we want to assign it to, along with the value. Anytime we do a lookup, we're going to replace that with the g function, g forget. And anytime we want to assign a function expression to a variable, which is gonna be the only way we'll be allowed to use functions, we'll use f. And the f function will take in the name of the local variable to which we would like to assign this function we'll be creating. Then the list of params that it would take in, and then that amnesic function body. Notice it has no parameters. So with these substitutions in place, our task is to take a block of code that looks like this. So this is a very standard non-trivial closure example. There's an outer function that when evaluated returns an inner function, which when evaluated returns an array of x, y, and z. Now, the important thing for you to notice here is that we're going to see a few edge cases come in. One, in the inner function, we're inheriting the variable y from the outer, and x in the inner is going to shadow the outer one. And also, when we execute these functions, we'll be executing them out of order from where they were defined. So for example, we define the outer function first, but, and it will be evaluated first, but the inner function will be evaluated out of order. So we're gonna throw through a few edge cases in here. So with those substitutions, we'll end up with code that looks something like this, which will be a whole lot faster. So with those substitutions in place, all we need to do is write the S, G, and F functions. So without further ado, we are going to completely rewrite closures in 70 lines of code. So let me tell you a little bit about the project that I've set up here. Hopefully the text is large enough for you. So first thing is I'm gonna take a test-driven developer approach, which means we're going to pick aspects of clopes that we all know and love, and then write some specs to describe it. In this case, to save time, I've already written those specs. So first of all, we're going to describe a scope object. This scope object is going to be the object that handles the S, F, and G functions that we call on it. And also, just for brevity, we're going to assign those functions, get and set, in this case, to some local variables, just so we can quickly use S and G without having to do scope.get or scope.set. So the first test is going to describe how this works for a global context. So this is back to the good old days of Fortran and X86 assembly, where you didn't have a way to do some work without polluting the global environment. All you had was the global environment. So first of all, like any good test-driven developer, we should make the screen big enough to see. So first off, we should run this spec and make sure it fails. And of course, it fails. We haven't even defined the scope object. So as you'll notice, we're assuming there's an object called scope and the scope is going to have that set and get method. So let's go over here to our little JavaScript file and start writing this. So first off, we're going to define a scope object. I'm just going to use an iffy here because in our implementation of scopes, we are allowed to use some of JavaScript's handy features just for now. So first off, we're going to make sure that we isolate the scope definition from the environment just because we're good JavaScript programmers and we'll write a basic constructor. And this constructor will just keep track of one thing, a dictionary mapping from local variable names to their values. So this is very much the concept of a global context. You map from a variable name to its value. So that's all we need to remember. Now for this to be of any use, we need to define those get and set methods. So let's go ahead and do that. We'll write get and get will take in one thing, the key or the variable name we want to look up. And this is really simple. All we need to do is look up that particular key in the dictionary and return it. Get is also going to be, excuse me, set is also going to be very similar. It takes in a key and a value and then it will set the entry in that dictionary to the value and we don't need to return. So let's flip back to the test and perfect. We have our first spec passing. We've rebuilt global context, awesomeness. So we need to move on from here. However, we had quite a few more specs to satisfy. Let's see if we can find that block. All right, so now what we want to do is define a general context. So some of you may have come from graphics programming. In graphics programming, whenever you want to apply a chain of transforms, you could either compute all those transforms together with matrix multiplication and do it manually or you could let your language do something like a context push and pop. This is very common if you want to build, say, a robot, but you want to transform all the robot's parts in a particular way. You might first transform the entire environment and then start building the robot with some predefined transformations. Also, this is very common in 2D graphics where you can apply a stroke or a color fill. But as soon as you leave that context, you revert back to whatever the stroke and fill was in the parent context. Well, scopes are very similar to context in the way we can push and pop. So in fact, we're going to borrow that terminology here. Notice here in our little before block, we've added a push and pop method. And push and pop allow us to create a new context and then return to the parent context. So let's take a look at these specs first. This is what we need to get working. The first is standard in context. We should be able to isolate any work we do in inner context from the outer context. Second, by default, whenever we refer to a variable by the same name in the outer, for example here, we're referring to X from an inner context. By default, we should inherit the value from the outside. However, if we happen to have name conflicts, for example, we define X in the outer and X in the inner, then while we're in the inner context, the X in this case equal to three should continue to equal three. But as soon as we pop it, we should not have polluted the external environment. This is the whole idea of context. So let's go ahead and make this work. This will be a little bit more involved, but should still be fairly straightforward. So just to start off, just to see how good our tests were, let's just write a blank push function and we'll write a blank pop function and see what passes. All right, we have some failing tests. However, you'll notice right off the bat, we have these two tests that are actually passing. The first one is that variables by default should be inherited from the outer context. Well, of course that makes sense. We're still dealing with a global context. So even though we supposedly pushed the context on, we didn't actually, so we're still looking at the exact same variables. All right, so to make that test pass, to make sure variables are isolated, why don't we just set the dictionary to a blank object every time we do a push and we'll do the same thing for a pop. This should definitely isolate the variables, right? And in fact, it does. Now our isolation test passes. However, we broke all of the other tests in the process, all three of them. So that wasn't really a great trade off. So let's just make push work off. So whenever we push on a context, what we want to do is for our dictionary to give us a clean slate to work with, but anytime we do a variable lookup, it should default to whatever was in the parent context. Well, anytime we wanna do this sort of inheritance, we are in JavaScript, we can actually use prototypes. So let's use Douglas Crockford's prototypical inheritance method for doing this. So first let's write our push method. Our push method, what we're gonna do is we're gonna write a method called fork-dict. I'm just using a terminology fork here interchangeably with inheritance. So what we want to do is we're going to define this fork-dict method. This fork-dict method, we'll just use Douglas Crockford's pattern for prototypical inheritance to create a new object that inherits the default values that were in the prior scope object. So we'll call this fork-dict. It will take in no arguments and we'll just do the standard method here. First off, we'll save off what the current dictionary is and then we're going to define our little donor anonymous function. This is just so we can have a constructor to work with. And then we're going to set the prototype, prototype equal to object.create-dict. This is a new method available to us in many browsers. I'm working on the bleeding edge so I apologize to all of you who have always written the polyfills. I do not have a polyfill in place. So we're going to set the prototype to that new object which means that our prototype is a brand new clean object whose prototype equals our dictionary, in this case the parent dictionary. We're going to set a few methods on this just so debugging is a little bit more straightforward. We'll set the constructor to F, this anonymous function. And then when we go to pop context, we need a way to revert to the previous context or in this case, the previous dictionary object. So let's define a Dundascore parent property and we'll set it to the dictionary. And then at the end of all this, we're going to invoke our constructor and return the object created. So fork-dict is just creating a dictionary which defaults to all the values in the parent hash which means that we can create this nice lovely chain of dictionaries that all refer to their parent. That's gotta be incredibly memory efficient, right? We didn't have to copy anything over. So let's try this now. Well, we see that now that spec passes and the last spec passes as well. But we haven't yet written a proper pop method. So that means that whenever we have any variable shadowing, as soon as we set a variable in the inner context that was using the outer context as well, we're actually polluting the environment outside. So we don't want that. So let's go rewrite pop. So pop is going to be really simple. All we need to do is look up the current dictionary parent because we were so kind as to create that little chain earlier. So now if we run this, all of our tests pass. So this means that we have the essential graphics idea of push and pop working exactly. So the only problem with doing this is we're having to call push and pop. What we're all used to is doing ifs. With ifs, what we can do is just create a function as though it were a boundary and then do our work and then at the very end invoke it without polluting the global environment. So let's go and enable some specs for that. We'll enable these specs for nested ifs. So at this point, we aren't going to use push and pop manually. We're going to define this F for funk helper and that funk helper is going to allow us to create a function and assign it to a local variable in the current and space. So first off, let's make sure this test fails. And indeed it does. We haven't even defined that F helper. So let's go start defining it. So down here at the bottom, we'll write that. Now funk, as you'll recall, takes three things. It takes the name of the local variable to which we want to assign this function we're creating. It also takes in the list of params, the parameter list that the function would take, along with that amnesic function body. And that function body should not expect to have any arguments. So I know right off the bat, I'm going to have to memorize this. And then what we want to do is we want to use the set method, which we defined earlier on scope, and we want to set the local variable by name that we passed in, to a brand new function. Now we're doing it as a brand new function because we need a wrapper around our function so we can call push and pop before we execute that amnesic function body. So right off the bat, we know that we're going to have to call push, and we know that at the end we're going to have to call pop. Somewhere in here, we know we're going to have to execute that body. Now that body, as you'll recall, is not allowed to access any local variables. But because we pushed on a new context, we've given it a workplace when it calls s and g. Now I probably want to save off whatever the return value was so I can return it later on. Now there's only one thing missing here. We haven't done anything with params at all. So params are just local variables that are created as soon as a function begins executing. They're visible only in that context. So what we could do is we could loop over every single param and also grab the arguments that this anonymous function wrapper is getting and set it. But in the interest of dryness, we're going to actually define a little helper method. We'll call it args, and this args helper will take in the list of parameter names along with the parameter values, which in this case is gonna be the special object arguments that JavaScript provides to us. Get our semicolon. So let's write that little helper method. Should be pretty simple. It's basically just a loop. So it takes in the names of the variables we want to assign along with their values and it'll just loop over every single one of those names and assign it. So we'll call this.set, grab the current name, grab the current value. And with that, I think our iffy test might just pass. And indeed, now we have our little fhelper working and it's working like a proper context. It isolates changes in the inside but inherits changes from the outside by default. So now we have nested iffy's working. And if we look at our example, we see it's just the ffunction and as soon as we define a function, we retrieve it and execute it. So this is very close to the example we started the whole demo off with. Now, there's one problem, however. Let's move on to the next set of specs. So we're going to define the behavior for a proper closure. So when we run the spec, we see that we should have gotten the result three comma undefined comma four. Or excuse me, we should have gotten three comma two comma four but instead we got three undefined four. Now, if you worked out that example I showed you on the slide earlier because of variable shadowing, we should have gotten three comma two comma four. However, we didn't. And this is because we have a difference of scopes. We're actually dealing with an execution stack versus a lexical stack. And I'll show you exactly what that means in a moment. So if we take a look at our definition of funk, we'll see that as soon as we start calling F which basically means we're defining a new function we aren't actually executing it. Nowhere in here are we keeping track of what the current scope is. We're not asking, hey, scope. What's the current context or what's the current scope rather? Nowhere are we doing that? The only place we seem to do that is when we actually execute this function in here. Notice that when we go to do push that push method actually asks what's the current scope and then forks off of it. Which means that our scope is actually defined by when it's being run as opposed to where it was defined. Well, in JavaScript, we deal with lexical scope which means that the scope or the parent scope rather is determined by where it was defined and not by where it was executed. So we need to fix this. But first off, we should notice there's quite a bit going on in here. There's several responsibilities that we're handling in this one scope class. It's got to handle creating a scope, getting and setting variables in it. It's even got to create a function and it's got to have a global registry of sorts of all the scopes that are currently on hand. Well, that's not good design. So let's try to fix this. Whenever we talk about a closure, there's inherently the idea of a function body which is just the list of statements. It's the raw bucket of code. And also the idea of what variables do I have access to and what variables can I change? So we call that concept a closure. A closure is essentially a function plus a scope. So that means that we probably need to keep a registry somewhere that maps all functions created to their corresponding scope. So first of all, let's skip onto the next set of specs and fix something. What we're going to do is instead of creating a scope, we're actually going to migrate all those responsibilities to something we'll call a closure registry. And to do that, we'll just define this closure registry using our little iffy pattern. And we'll define our constructor. Right now our constructor won't take in any arguments or anything. All it's going to do is be initialized with a blank object. That object is going to map from functions to a scope. So right off the bat, we should ask ourselves, okay, what about our get set and args methods? Right now those are all defined on scope, but it seems the closure registry is going to be kind of our waypoint to using that. So right off the bat, we're going to use a little helper. If you guys are interested in exactly how the helper works, feel free to look it up in the repository. I'm going to borrow the delegation pattern from Ruby. I've written a little helper here called delegate. It lets you give a list of methods that you want to delegate, what object it should create them on, and what object it should delegate them to. So we want to delegate the get set and args methods that could be called on this registry, and we want to delegate them from the closure registry's prototype, which means we're going to basically define, it'll automatically define some methods, and it's going to delegate them straight over to the current scope. Now how do we get the current scope? Right now we don't have a way to really keep track of that. Well, let's assume that our closure registry keeps track of the current closure that is being executed. Not the closure that's being defined, but the one that's currently being executed. Right now, just for kicks and grins, we'll set it to an empty object. And what we'll do is this delegation helper accepts a function that gets evaluated, and we can ask what is the scope for the current closure and return that, and that's the object to which these methods will be delegated. So that means right off the bat, we need to define this method, scope for current closure. Now for now, we'll just leave that blank. Let me hide a nerd tree for you. There we go. So we'll just leave that blank for now. Now let's revisit the whole responsibilities issue. We've still got quite a few functions here in our scope class. I know right off the bat, that push and pop really don't belong in here because they manage creating new contexts and linking them together. Scopes should really just be keeping track of what variables it has set and how to update them. So let's go ahead and move those up here. I'm gonna comment out those implementations for now because they won't work in this particular context. And func as well. Func is actually a little bit of a misnomer. It should probably be called closure because it deals with both the function body and with the scope object. So I think this really belongs up in the closure registry. So we'll move that up here. We'll remember to rename the prototype it's on. All right, so this seems like it's in the right place. That looks a good bit nicer. So the next thing we probably need to do is we need, when we're defining these functions, to grab hold of what the current context is. Because as we saw, whenever we just called push before, it was just grabbing whatever the current context was at the time of execution. Well, that's not how closures work. They're based on the lexical scope when they were defined. So that means we should probably somehow memoize what the parent context is so that way this new function wrapper can access it when it goes to push on the new scope. But in fact, we'll just shorten this down a little bit. What we'll do is we'll go ahead and fork the brand new scope. That's going to be used for this function when it gets executed. So somehow we'll grab the scope for the current closure and then we're going to fork it. Now we haven't written this fork method. All the fork method does is invoke our fork dict and return a brand new scope object. So let's write that. So this fork method is going to return a brand new scope whose dictionary is initialized with a forked version of this current scoped ones. So you can just think of this as a nice, it's not a constructor method, but it creates a brand new scope for us to use in the spirit of immutability. So we'll pass in the results of calling a fork dict. Now the problem is right now our scope constructor doesn't take in any arguments to initialize it with. So we'll fix that. We'll allow it to be passed in the dictionary to start with. Otherwise it'll just default to an empty object. Now we just need to write that scope for current closure method. Now before we do that, right now I've been assuming that our registry has to be an object. It has to map from a function somehow, even though keys and JavaScript have to be strings, somehow we're going to map from functions to their scope. But we can actually make an interesting observation. Whenever we're executing code naturally there's only one scope in effect. When we're executing code. Furthermore, whenever we go to enter a new scope, as soon as we have finished executing that function we immediately pop off that scope and return to whatever the previous one was. Push and pop should sound kind of familiar. We're dealing with a stack. So unless you want the debuggability of keeping track of all functions in all scopes, our registry actually just needs to be a stack. In this case an array will do just fine. And in fact we don't even have to keep track of whatever the current closure is. Because whatever the current closure is doesn't matter. All we care about what is the current scope? Which means that we don't even really need to keep track of the closure because the current scope is just whatever is on top of that registry stack. So with that in mind we can go ahead and write some of these methods. First off let's write scope for current closure. So scope for current closure is going to be really easy now. We just need to get whatever object is on top of the stack. So let's do that. We'll return the registries and get its last element. So that gives us our scope for current closure. There's only two other things we need to define which is push and pop. Now intuitively push and pop aren't really doing anything fancy. All they're doing is pushing on a scope that's passed in. We have to pass it in because push is going to be called at a time different from when it was actually defined. So the way we would implement this is we would call registry.push. We would just use the array method and push that new scope on. And we would do the exact same thing for pop. So in fact I'm gonna delete all this boilerplate code and just use our nice little delegate helper. So that delegate helper is going to delegate all calls to push and pop from the prototype directly to that registry array. So this seems like it should just work. Let's check JSN and make sure I didn't do anything abominable like leave off a semicolon. We couldn't have that. All right, let's flip back to our specs. Let's ignore those earlier specs because naturally I've broken them. All right, now just to test that matter. All right, so first off we notice our areas. We cannot read property fork of undefined. That means that somewhere where we expected a scope object we tried to call fork but it was undefined. Well, let's go back to our code. When this closure registry first starts off, it starts off with an empty stack. Right off the bat, when we go to use the set and get helpers or push and pop for that matter, those rely on grabbing the current scope. Well, when we start out this code, the stack is empty, which means that scope for current closure down here is returning undefined. That's not what we want. Every JavaScript program starts out with a global scope to begin with. It's almost as though there were a function that wrapped around all of your code. So to fix that, we're not gonna start out with a blank stack. We'll start out with a blank scope as the first object and this will be our global scope. So anytime we do push and pop, we should never push and pop and end up with an empty array. We will always at least have that global scope. And now if we run it, that last spec passes. So congratulations in 70 lines of code, you have completely rewritten the closure implementation in JavaScript and you can nuke closures entirely from your code base because as we all know, they're insanely slow. All right, let's see if we can get back here. All right, so you may ask, should I actually use this? Or rather, let's start with something else. Can I use this and can I have my code converted over automagically? And yes, you can. There's a transpiler up. You can go to the web page now and plop in any of your code. It will actually pull in, it will transpile any substitutions, variable assignments, lookups and function expressions. It will automatically substitute those. This is online, so you can just drop it into the browser. In this case, I put in our example and it will output the much, much nicer looking code. It's even indented all properly. This makes me really happy. So this will all totally work and you can go do it right now. Hopefully you don't bombard GitHub pages too hard. Now, the question that you all are really asking is should I actually use this? And my answer to you is totally because JavaScript and JavaScript is one more way to get brownie points with your employer and to get a little bit more job security. If you drop in a custom closure implementation like this, I guarantee you'll be managing that code base for quite a while. And then since we've been talking about the future of JavaScript quite a bit this morning, you may ask is this the future of JavaScript? Is this something that isn't draft or strawman proposal because no one wants to type the var keyword anymore? And I don't know anything about proposals or anything but I think this is definitely the future. At least for now because my next talk is going to be one really weird way to rewrite prototypes. And to do that talk, my plan is to start out with local variables and use the vowel method so we can dynamically create some code, do a little transpiling, and then execute it to do prototypes. And by all benchmarks, it's looking really good. Thanks.