In a previous post we looked at the new class keyword in JavaScript.
We’ve always had the ability to create objects in JavaScript, and give these objects data to hold and methods to call. In fact, we could have written an “employee” object using a simple object literal instead of a class.
let developer = { name: "Scott", doWork: function() { return `${this._name} is working`; }, get name() { return this._name.toUpperCase(); }, set name(newName) { if(newName) { this._name = newName; } } }; expect(developer.name).toBe("SCOTT"); developer.name = "Alex"; expect(developer.doWork()).toBe("Alex is working");
The advantage to having a class is how we can create multiple developers just by using the new keyword and not have to write out an entire literal definition like the above code. Each object is unique and contains its own data, but the method implementations are consistent and shared.
let dev1 = new Employee("Scott"); let dev2 = new Employee("Alex");
In fact, even before the class keyword came along, we had the ability to define a blueprint for object construction in JavaScript. The approach was one we called the “constructor function and prototype object” approach.
let Employee = function(name) { this._name = name; }; Employee.prototype = { doWork: function() { return `${this._name} is working`; }, get name() { return this._name.toUpperCase(); }, set name(newName) { if(newName) { this._name = newName; } } }; let developer = new Employee("Scott"); expect(developer.name).toBe("SCOTT");
As it turns out, all the class keyword is doing behind the scenes is setting up a constructor function and prototype object. This means all of the tricks we’ve learned in the past still work. For example, “borrowing” a method from a prototype object:
class A { doWork() { return "complete!"; } } var result = A.prototype.doWork.call(); expect(result).toBe("complete!");
The instanceof operator also works as expected.
class A { // … } var a = new A(); expect(a instanceof A).toBe(true); expect(a instanceof Object).toBe(true);
You can also still augment all instances of a type by modifying prototype objects (if you like to live dangerously).
class A { } A.prototype.newMethod = function() { return "new!"; }; var a = new A(); expect(a.newMethod()).toBe("new!");
You can think of the class keyword as being syntactic sugar for creating constructor functions and prototype objects. However, there is more to the class keyword than what we’ve seen so far. We’ll look at class inheritance in the next post.