Sessions is temporarily moving to YouTube, check out all our new videos here.

Managing States in JavaScript via Prototypal Inheritance

Almir Bijedić speaking at viennaJS in May, 2017
787Views
 
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

Watch how to use prototypal inheritance in JavaScript to do state management. Code snippets by Andrea Giammarchi @WebReflection, related blog post: https://www.webreflection.co.uk/blog/2016/12/23/javascript-proto-state


Transcript


- [Instructor] Hello, my name is Almir. And today I'm gonna give a quick talk on five kilobytes smaller undo, or how to use prototypal inheritance in JavaScript to do state management. Five kilobytes smaller undo. What does that sound like? Anyone? Redux, maybe? Anyways, we're going to show a code snippet which helps us manage states similar way as redux does it. So, just the small part of the functionality where you can have one state and easily undo to any of previous states. And also diffing between them is very easy as you'll see. But before I start on that, I just wanted to quickly revise about prototypal inheritance for those of you who maybe don't know about it. It has to do with those babushka dolls over here you see, it's something similar. Prototypal inheritance is the object-oriented way how JavaScript works. Basically, when you create an object like this here on top, this car object will have a prototype property of its own which will point to its parent, which is the actual JavaScript base object. In this case since we just instantiated this object right now, if you console log this, the second line here, car.proto, you will get the base object from JavaScript and then if you also call the prototype of that prototype, you get null and that's how you know that you're at the end of a prototypal chain in JavaScript. Also what's important is that if you want to create a new object whose parent is not the base object but something else, for example the car from the previous slide, we use the Object.create function. We give the object we want to be the parent as the parameter and it returns the child object. And what's interesting about this, what's the point of all this, is that the properties of the parent object can be accessed from the child objects. For example, if we console log the mustang.make, even though we never assigned it, it will lookup to the prototypal chain to the car object who is the parent of the mustang object and console log the Ford, even though the mustang object itself does not have the make property. So if we console log just the mustang, we would just get the property we assigned over there. Alright, now that we get that out the way, this here, we have a constructor that takes some object and it assigns all of its properties to an instance of this constructor, of this object. Then also we set the prototype, the next function, it takes two parameters: the old state and the new state. And we simply set the parent of the new state to be the previous state and we return that new state. The object.create function you saw earlier, we can also do it with, it does the same setPrototypeOf. But with this one, with setPrototypeOf, you can set the prototype after the creation. So object.create is only when you're creating the object, you immediately set its prototype to the past thing, object. And with setPrototypeOf, you can set to an already instantiated object who can set its prototype. And then the previous, if we want to get the previous state, it's getting quite obvious I hope, we just call the getPrototypeOf function of the current state of past tense state that will return as the parent which is actually the previous state. And we also have to check if the prototype is state prototype, that means that we got to the end to the first state we instanced in the beginning. Alright, so what can we use this for? It's really easy to put some object and save its state and then update the state a few times and rolling back to a previous state is as simple as calling this line here, which is state.prev of the current, with current is an instance of the state. For example, we could use it in some kind of game where you are remembering the mouse position every second. This previous x function is similar like to previous function, but x times. So if we want to get the fifth previous state, we just pass then as the second parameter over here. And then we get five states, five states behind. And we could use this to save the state every second, ah you don't see that. We could get the state that was active five seconds ago with just by calling this one line over here. Also, we don't have to worry about name clashes because we don't have to name anything here. Everything is in the prototypal chain. And also, it's possible to branch from one state into two, or three, or however states and it's also possible to roll them back onto the state where they branched from. One problem, if we have a state and we wanna know all the keys for that state, if we call Object.keys, Object.keys only returns the properties that are the own properties of the object, not the inherited ones from the prototypal chain. So if we would call Object.keys on, for example, person state which at the instantiation has just the name Almir, and then later we update it to the age, we would get that the person only contains age. If we wanna know all of the properties that it has from its prototypal chain, we can just use this simple function because here, the second line, for k in state, the for in syntax, it returns not just the properties, the own properties of the object, but also all the ones in the inheritance chain. So this, for the previous example, we would get an array here with both name and age. Also if we wanna diff between two stages to see what was updated, it's just simply calling Object.keys because we will always get just the object of keys. Also if you wanna diff, this one is only if we are diffing the previous state, diffing between multiple of them so, you do multiple updates and you wanna see what changed between those two, it's not too complicated either. See the snippets on the left side here? We are basically just checking what returning the state to the previous one with a reiteration when it's the same, stop it and return all of the collective keys. And one more thing, if someone wants to make this immutable, so that every state is immutable, we can just simply change the initial function to call an object freeze on the object just you have to be careful with this because if setup contains a property which is also an object, then you have to recursively call it. So this would work for simple cases. If you wanna make sure that it's immutable all the time, then it needs additional lines. That's it, thank you, questions?