JavaScript: The Hard Parts, v3

Private Static Fields

Will Sentance
Codesmith
JavaScript: The Hard Parts, v3

Lesson Description

The "Private Static Fields" Lesson is part of the full, JavaScript: The Hard Parts, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Will finishes the OOP discussion by demonstrating how private static fields can be used to store shared data accessible only inside the class constructor, preventing external modification. He emphasizes the importance of understanding these differences for writing resilient, well-structured code and for technical interviews.

Preview

Transcript from the "Private Static Fields" Lesson

[00:00:00]
>> Will Sentance: Our final, final piece of code, here it is. Now we can also add private data. That means it can't be accessed outside of this, this setup, outside of things related to user creator that is attached not to the individual. And let me just make it clear, if we now call, let's just get rid of our, let's just get rid of our using of user one increment, just so we can keep working on this same code and not have to write it all out again.

[00:00:36]
Now let's also, we ran user one, sorry, we ran user creator once, new keyword, stored it in user one. There it is. Let's actually do another call. Yeah, I know that the function, the constructor has a new line of code, if usercreator.hashcount is greater than 2, throw error. We're going to, let's run user, well, this is the challenge of, this is the challenge of making the changes on the code as we go.

[00:01:14]
Let me remove, forgive me people, I'm going to remove our private #score just for now, because it's no longer in here, right? We did, we're doing a new one, so forgive me, I'm going to remove that now and go back to what we had before, which was score, just because I want to make sure. And we don't have logged in false here anymore in our fields, and we get back to our regular school. Okay, and actually this is no longer being incremented to 4, it's still 3.

[00:01:49]
So from our first running here of user creator with the input of Ari, in we went, and actually now we do a little bit of extra work, because when we declared, when we created our user creator class slash function object combo, we actually got another final, and I promise you this is the final one, we got another final. We've got another final new field we could work with, and this one sits on user creator directly in its private fields, where we have #hashcount is set to 0, directly on the function object combo on its object bit, in a set of private properties that can only, we will not be able to write usercreator.hashcount.

[00:02:54]
We cannot write usercreator.hashcount and try and increment it. It's only going to be available from inside of stuff associated with user creator, not by global. We can't do that. That sounds like when you're reprimanding a child, that's how tall my voice is. You can't do that. So we get our private data on user creator, hashtag count is set to 0, only viewable by user objects that get created out of running user creator, our constructor bit.

[00:03:25]
So let's do one. Well, the first one here, we've already done most of it, but let's just tweak it. And first, alongside doing all of our automated stuff with a new keyword, when we run user creator in its constructor bit, the first thing we actually do is say if user creator.hashcount. We can do this bit right after our, right after our creation of the object and setting the bond. I know we're sort of going back a bit here, so forgive me.

[00:03:58]
We've already got our name Ari and score 3. We're going to do that in a second, but we can first check user creator.#hashcount. Do we have access to it? We do, because we're doing it inside of our constructor function, user creator constructor function, and when we do, we check, is its count greater than 2? If it is, we'll give an error. Well, it's not, it's 0. So it's less than 2, and we go ahead and set this.name is the value of the argument name, which is Ari, and we do this.score, the value of the score.

[00:04:48]
And then we also go and increment the shared private data of usercreator.hashcount. We increment it by 1. And now, and now we're going to do one more call together of our user creator to see whether, well actually, you know what, let's do the second one user 2. Be done already. From our, so our user 2 is the return of calling with a new keyword, our user creator function, a penultimate time with J and 5, and we know that that returned out from all the help of the new keyword, all the automation, it returned out name J, score 5, and our hidden proto link up to the shared set of functions, meaning we can still do our dream thing.

[00:05:51]
User 2.increment, go ahead, Chris. And because of the static keyword, it knows not to set count to 0 again the second time we, because we're not calling the constructor, we're not calling the overall class, right? We're just that bit was, and that's why it's such a gotcha, right? Thank you so much to Chris for asking that. Chris is like, but when I call user creator again, when I call user creator, I'm calling the function bit, which is just the constructor bit.

[00:06:17]
Well put by Chris, but now let's do one all together, so we can be absolutely sure of Chris's clarification there. We're going to call user creator one last time. This time we're passing in Tam with a score of 9, with our new keyword, and we're going to, we're going to do it all together. In fact, you lucky things, we're going to go round each person and each person is going to do a line. Brady, you're up first, because you're in that corner there.

[00:06:52]
Brady, what's our first, what is the first thing we're going to do here in global memory, bottom left hand corner? We are going to assign the constant user 3. Yes, to the return value of doing a bunch of work automated, but honestly, in the end, we hope that we get an object out of it that has a name property of Tam, a score property of 9, and a link. Well, actually, hold on, it's not going to do it, is it?

[00:07:22]
Okay, well that's probably going to be a bit easier, isn't it? We hope it's going to do that. Okay, so Brady, we're going to need to create a brand new what? Execution context. Yes, hold on, Brady. Yes, exactly, and into it we go, but to run what? To run user creator. The whole class thing? The class was just a command to JavaScript, go save that constructor function bit as the function, so when we put parens on the end of user creator, run that bit, and then it was to save increment on the dot prototype bit.

[00:07:56]
We don't have login anymore, but just to save space, and to save this private score, which is now 2, because we incremented it again with our second running of user creator. Okay, when we call user creator, we're just running the function bit, just as before, nothing changed. And we have our new keyword that's going to automate a bunch of stuff. Into it we go, and we have in our local memory, I'm going to turn to you now.

[00:08:31]
Ryan, who's been asked less than, Ryan, what are we doing? What is the parameter name we use? Yeah, parameter of name will be set to Tam, and then the parameter score will be set to 9. Beautiful. Well done for Ryan. We're looking at the code of constructor, because that's the function we're running when we put parens on the end of user creator, which is still just a function object combo. It was set up by class, which added a bunch of stuff to it, but it's still just a function object combo.

[00:09:00]
And we go in, and the first, this is actually quite nice, we're going to save ourselves doing any further work, because we're going to hit our conditional. If it sets up this too, right? Oh, yes, well done. Well done to Chris, it's going to set up a bunch of stuff, isn't it? Which we're not going to be able to use, right? But never mind, so the first thing we're going to do is set this to be what, Chris?

[00:09:32]
An empty object. Well done, empty object. Oh dear, you can see I'm getting tired. Then, as you, I think therefore are very aware, Chris, what's it going to have that empty object automatically have? A hidden proto link to the class's prototype. Yeah, why not call it, yeah, yeah. The function user creator in its object form's prototype property, which is an object, and I don't mind the term the class's prototype.

[00:09:53]
Actually, that's quite nice. That's actually quite nice because it's like really letting any person listening know. My problem is when one uses terms like class and it gives one the impression it's behaving like a traditional class in other languages. But you're very quickly telling someone it ain't when you say the class's prototype. Right, so setting it up to the object prototype here, which is at, let's write it in, technically at usercreator.prototype, which is that object into which we automatically had increment added.

[00:10:36]
I've still left login there from earlier, but yeah, if we just listed login, it would also be in here. Perfect. So it set the hidden proto to this user creator.prototype object into which we hopefully have stored, which we did, because we used the class structure that will put any functions we list at the bottom into prototype. Okay, now, is that everything we did with this? We would check the fields bit, but we're not adding any fields here to the individual objects that get returned.

[00:11:11]
If we wanted to do that, we wouldn't have used the static keyword in front that ensures this is attached just to the overall function object combo, or let's call it class. And we hit our first line of the body of the function, Chris, did I miss anything else? I don't think so. Okay, all right. Into the first line of the body of the function, where before we do our property assignment, we're going to first check against this private data attached to the overall class function object, where we check user creator.

[00:12:00]
It's a private property name, it's private field hashcount. And we see, is it greater than or equal to 2? Now, if we were to refer to usercreator.hashcount in global, could we get access to that data, Chris? No, exactly. This is part of, this is a genuinely new feature of JavaScript, private data. Only available inside of the user creator's function, the constructor function. And into it, and we check and we, sorry.

[00:12:35]
But we in here we can. So Chris, we go look for what? Usercreator.hashcount, which is on the object bit of user creator, which was all set up by the class structure. And do we find hashcount? Yes, we do, and its value is now 2. 2 is 2 greater than or equal to 2? Yes it is. It is, and therefore we throw an error. And thank God for that, a maximum number of users has been reached. This is amazing for shared data across all objects, in this case, all user objects get returned that can't be accidentally changed.

[00:13:11]
We can't go, what did we hear earlier from Chris? Wait, I can go and overwrite prototype? Well, we can still do that, but what I can no longer do is overwrite, for example, some shared data that I want all of my objects to have access to, because I use this new way of storing data on the class or function object, on its hidden fields portion or its hidden properties portion, not hidden, sorry, let's not call it hidden, private properties portion that is only available to us in our function that is constructing and creating the objects.

[00:13:52]
Wow, I am taken aback, people, and I think because we are getting to our very final, we're going to have some thumbs in a second, but I am taken aback by how much JavaScript developers, creators have leaned in to trying to reconstruct their classical object-oriented language, using a language that fundamentally, under the hood, is a prototypal language, one which uses access to other objects via this hidden proto property to try and reconstruct in other languages and built-in ability to access other functions, to access other methods, to have private data, to have shared private data, to have static class, to have static features or static fields on classes.

[00:14:35]
All of these things JavaScript is trying to recreate, but my goodness. And if you want to ask those tough interview questions, because these are things that if we don't understand under the hood how they're working, do not behave. I hope you can see, for folk who are coming from those object-oriented languages, do not behave under the hood how they behave in those languages, and therefore do not behave on the surface how they behave in those languages.

[00:15:08]
Excellent stuff, people. Prototype chain, a class, syntactic sugar, but honestly, increasingly, quite a lot more than that. And new field features give JavaScript some serious object-oriented capabilities. But folk, it's all prototypal under the hood. It means we're always implementing these classical OOP features on top of a powerful, but nevertheless distinct, and it ain't the same, from an object-oriented system, the prototypal nature of JavaScript, its prototype chain.

[00:15:36]
But there is a growing set of real OOP type features, where, if you come from these languages, they're legit. The new and class keyword were the first ones to give those that automate the prototypal work. All of this stuff is setting up the object, making the bond to the shared functions, we're turning out the object. But we now also get private and public static and instance fields, which is going to enable us to properly encapsulate, meaning the data and the functionality are truly bundled up together and never the two shall be accessed from elsewhere, well-structured, resilient code.

[00:15:55]
Tools that emulate many of the strengths of classical OOP, but for sure, only if we understand the prototypal foundations.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now