Check out a free preview of the full Deep JavaScript Foundations course:
The "Class Caution" Lesson is part of the full, Deep JavaScript Foundations course featured in this preview video. Here's what you'd learn in this lesson:

If you use an ES6 class, Kyle points out the areas of caution.

Get Unlimited Access Now

Transcript from the "Class Caution" Lesson

[00:00:00]
>> Kyle Simpson: So I wanna point out just a few things that you should be aware of if you start trying to color outside the lines. Let me show you a few of those places where the class you should be cautious. First off you could not extend an object, this actually I think my biggest frustration or objection, maybe my second biggest.

[00:00:23] You can't mix classes and object together, it's all classes or no classes. You can't just extend an object, why? I don't know, I have yelled and screamed and thrown a fit, they didn't pay any attention to me. That'll cause a syntax error, sorry, a run time error you're not allowed to extend an object.

[00:00:50]
>> Kyle Simpson: Even though this is supposedly just syntax sugar, so theoretically Foo and Bar are actual functions, you can't call them. You can't just call the Foo and more importantly, to my problem, you can't call Bar and override it's this or do any kind of this binding stuff. You can't do anything dynamic with it.

[00:01:11] You're not allowed to use those classes as actual functions, you're only allowed to use them within the new keyword. So, it's a full lock to it's all classes or no classes.
>> Kyle Simpson: You're not allowed to call the super function, sorry, you're not allowed to reference this keyword until after you've called the super function in the constructor.

[00:01:37] So it's very common for people to want to when they're overwriting a constructor and extending behavior, setup some stuff in a specific way and then call to the parent constructor. So you'd wanna do something like setup of this or set up some kind of thing, and then call to the constructor.

[00:01:51] That's not allowed, you have to call the super first. That's an unusual deviation from typical class-oriented languages because in typical class-oriented languages, the end class, the lowest derived class, the furthest down in the chain, is the one that creates and initializes the object. In JavaScript it's the reverse.

[00:02:14] The most parent class is the one that creates and initializes, so it's kinda like a TDZ error. This keyword is in its TDZ at this point. You can't use it until you've called the super all the way up, and then you can use it. I've seen a number of people run across that gotcha before.

[00:02:38]
>> Kyle Simpson: This one's hard to explain, but you've got to stick with me. I have an A class and a C class, and the C class extends A. So look A and C, and you'll notice that I declare this foo, which is this.1. Just gonna call that, and I call super.2, which is also gonna call that.

[00:02:58] So when I instantiate C and I call x.foo, I get one A, two A, exactly the way we'd expect.
>> Kyle Simpson: But now, what if I wanna take that foo function, this one right here, and I wanna dynamically rebind it to a different context. Like for example, to the B context.

[00:03:22] If I say x.foo.call (B), we might expect it to say one, two B because now we're saying this.one and super.two. Here is one of the crazy gotcha's, with .call and .apply, it overrides or dynamically binds the this keyword, but the super keyword is static. The super keyword stays fixed at the time you declare the class, and it can't be overridden by a .bind, or a .call, or a .apply.

[00:03:56] So if you have a mix and match between a this and a super in your function, your this keyword will be dynamic sensitive, your super won't and I've seen people run in to that bug before.
>> Kyle Simpson: The reason they did not make super dynamically dispatched as opposed to statically fixed is for performance, that's literally it.

[00:04:19] They said, well it'll slower to figure out super at run time. So let's just statically fix it and then just tell people don't try to color outside the lines. The super keyword is only valid inside of functions that are there as part of the class definition. You can add to a class definition.

[00:04:42] It is legal to say b.prototype.foo and add a new function in. But that newly added function cannot use the super keyword. The super keyword is only syntactically valid if the function is there at the time the class is declared, why? Cuz the super is statically bound.
>> Kyle Simpson: So you can't add to your class definitions and still use the super keyword.

[00:05:08]
>> Kyle Simpson: You also can't use the super keyword inside of objects that delegate up to prototype. I'm sorry, you can use them in objects and methods, but you have to use the concise methods syntax. So here I'm using concise ES concise methods, I'm able to use super keyword. Here is I do bar function, I'm not allow to use the super keyword, so you gotta stick with the concise method syntax.

[00:05:38]
>> Speaker 2: Is that for backward compatibility?
>> Kyle Simpson: It is because people used to use the word super as a variable in old functions. And so they wanted to add the super as a keyword only in brand new function types that nobody would have written.
>> Kyle Simpson: So it's that old backwards compatibility question.

[00:05:58]
>> Speaker 2: There's a question on Java Is this A B example why does super go second, I don't know.
>> Kyle Simpson: In this A B example why does super go second? I think they're asking several Bar, why does super have to be second here? I don't know if this is the slide they're asking about, but super has to go second because there, super has to go second because this keyword isn't usable.

[00:06:27]
>> Kyle Simpson: They're asking here, why does super go second? Super only has to go first in the constructor. This isn't a constructor, this is just a regular method. By the time that method's called, the this keyword is already been initialized, it's not in its TDZ anymore, you can use it.

[00:06:46] So I think that was probably the question.
>> Kyle Simpson: All right, so we can only use super inside of concise methods. And there's a pattern that I like to use because I still like using object.create. If I want to inherit from a class into an object, I might do an object.create of (A.prototype), which is gonna make me a thing.

[00:07:13] And this object.assign that I'm using here on line 6, it's trying to copy over from an object. So I have an object literal that's designed here and I wanna copy over to it.
>> Kyle Simpson: Should work, right? I would copy my foo method from the object literal over to the B object which has now linked A prototype.

[00:07:34] And I ought be able to call B.foo, and get a one A, two A printout. The problem is that the this.one will work because the this is dynamic, but that's super keyword is statically bound to the object literal, on line 6. And the object literal, the super keyword is gonna reference object.prototype.

[00:07:56] So it doesn't dynamically switch over to the A.prototype content
>> Kyle Simpson: The take away here is that, while class does have some nice syntactic affordances, there are more than enough corner cases that my caution to you is, stay within the lines if you're gonna play with classes.
>> Kyle Simpson: Don't try to do dynamic stuff.