In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).
In practice, we often need to create many objects of the same kind, like users, or goods or whatever.
As we already know from the chapter Constructor, operator "new",
new function can help with that.But in the modern JavaScript, there’s a more advanced “class” construct, that introduces great new features which are useful for object-oriented programming.
The “class” syntax
The basic syntax is:
12345678class MyClass {
// class methods
constructor() { ... }
method1() { ... }
method2() { ... }
method3() { ... }
...
}
Then use
new MyClass() to create a new object with all the listed methods.The
constructor() method is called automatically by new, so we can initialize the object there.For example:
When
new User("John") is called:- A new object is created.
- The
constructorruns with the given argument and assigns it tothis.name.
…Then we can call object methods, such as
user.sayHi().No comma between class methods
A common pitfall for novice developers is to put a comma between class methods, which would result in a syntax error.
The notation here is not to be confused with object literals. Within the class, no commas are required.
What is a class?
So, what exactly is a
class? That’s not an entirely new language-level entity, as one might think.Let’s unveil any magic and see what a class really is. That’ll help in understanding many complex aspects.
In JavaScript, a class is a kind of function.
Here, take a look:
What
class User {...} construct really does is:- Creates a function named
User, that becomes the result of the class declaration. The function code is taken from theconstructormethod (assumed empty if we don’t write such method). - Stores class methods, such as
sayHi, inUser.prototype.
After
new User object is created, when we call its method, it’s taken from the prototype, just as described in the chapter F.prototype. So the object has access to class methods.We can illustrate the result of
class User declaration as:Here’s the code to introspect it:
12345678910111213141516class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
Not just a syntactic sugar
Sometimes people say that
class is a “syntactic sugar” (syntax that is designed to make things easier to read, but doesn’t introduce anything new), because we could actually declare the same thing without using the class keyword at all:1234567891011121314151617// rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi();
The result of this definition is about the same. So, there are indeed reasons why
class can be considered a syntactic sugar to define a constructor together with its prototype methods.Still, there are important differences.
-
First, a function created by
classis labelled by a special internal property[[IsClassConstructor]]: true. So it’s not entirely the same as creating it manually.The language checks for that property in a variety of places. For example, unlike a regular function, it must be called withnew:Also, a string representation of a class constructor in most JavaScript engines starts with the “class…”There are other differences, we’ll see them soon. -
Class methods are non-enumerable. A class definition sets
enumerableflag tofalsefor all methods in the"prototype".That’s good, because if wefor..inover an object, we usually don’t want its class methods. -
Classes always
use strict. All code inside the class construct is automatically in strict mode.
Besides,
class syntax brings many other features that we’ll explore later.Class Expression
Just like functions, classes can be defined inside another expression, passed around, returned, assigned, etc.
Here’s an example of a class expression:
12345let User = class {
sayHi() {
alert("Hello");
}
};
Similar to Named Function Expressions, class expressions may have a name.
If a class expression has a name, it’s visible inside the class only:
1234567891011// "Named Class Expression"
// (no such term in the spec, but that's similar to Named Function Expression)
let User = class MyClass {
sayHi() {
alert(MyClass); // MyClass name is visible only inside the class
}
};
new User().sayHi(); // works, shows MyClass definition
alert(MyClass); // error, MyClass name isn't visible outside of the class
We can even make classes dynamically “on-demand”, like this:
Getters/setters
Just like literal objects, classes may include getters/setters, computed properties etc.
Here’s an example for
user.name implemented using get/set:12345678910111213141516171819202122232425class User {
constructor(name) {
// invokes the setter
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Name is too short.");
return;
}
this._name = value;
}
}
let user = new User("John");
alert(user.name); // John
user = new User(""); // Name is too short.
Technically, such class declaration works by creating getters and setters in
User.prototype.Computed names […]
Here’s an example with a computed method name using brackets
[...]:Such features are easy to remember, as they resemble that of literal objects.
Class fields
Old browsers may need a polyfill
Class fields are a recent addition to the language.
Previously, our classes only had methods.
“Class fields” is a syntax that allows to add any properties.
For instance, let’s add
name property to class User:So, we just write " = " in the declaration, and that’s it.
The important difference of class fields is that they are set on individual objects, not
User.prototype:We can also assign values using more complex expressions and function calls:
Making bound methods with class fields
As demonstrated in the chapter Function binding functions in JavaScript have a dynamic
this. It depends on the context of the call.So if an object method is passed around and called in another context,
this won’t be a reference to its object any more.For instance, this code will show
undefined:The problem is called "losing
this".There are two approaches to fixing it, as discussed in the chapter Function binding:
- Pass a wrapper-function, such as
setTimeout(() => button.click(), 1000). - Bind the method to object, e.g. in the constructor.
Class fields provide another, quite elegant syntax:
The class field
click = () => {...} is created on a per-object basis, there’s a separate function for each Button object, with this inside it referencing that object. We can pass button.click around anywhere, and the value of this will always be correct.That’s especially useful in browser environment, for event listeners.
Summary
The basic class syntax looks like this:
123456789101112131415class MyClass {
prop = value; // property
constructor(...) { // constructor
// ...
}
method(...) {} // method
get something(...) {} // getter method
set something(...) {} // setter method
[Symbol.iterator]() {} // method with computed name (symbol here)
// ...
}
MyClass is technically a function (the one that we provide as constructor), while methods, getters and setters are written to MyClass.prototype.In the next chapters we’ll learn more about classes, including inheritance and other features.

Comments
<code>tag, for several lines – wrap them in<pre>tag, for more than 10 lines – use a sandbox (plnkr, jsbin, codepen…)Thus in solution (rewrite with class) "render", "stop" and "start" become part of prototype of newly created object.
But in original code these methods become part of an object itself
Additionally, with the solution's code, when you call the stop, it would loose its "this" value. If we don't want to rewrite our methods to become the object's property, we can bind the method to the object itself when calling it:
setTimeout(clock.stop.bind(clock), 2000);class User {
constructor(name) {
// invokes the setter
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Name is too short.");
return;
}
this._name = value;
}
}
http://javascript.info/prop...
name="something"
and
this.name = "something"
class User {
name = "Anonymous";
sayHi() {
alert(`Hello, ${this.name}!`);
}
}
new User().sayHi();
here if i would make
what values will be stored in obj
let clock = new Clock({template: 'h:m:s'})? I've been through every lesson in this course and don't once recall seeing such syntax.It looks like this when Clock constructor get invoked . {template} = {template: 'h:m:s'}
The newly created object 'clock' will have template = 'h:m:s' as its property
tCopy = {...tOrig}-- but this leaves thetOrigmethods behind, since methods are flagged as non-enumerable. I can circumvent the problem by using the constructor to define the methods, because the methods are then treated as functions, and functions appear to be enumerable. But this approach seems to defeat the purpose of the class!callandbindto tell the methods to use the copy as "this". I'm pretty much lost, here.tCopy = Object.create(Object.getPrototypeOf( tOrig),
Object.getOwnPropertyDescriptors( tOrig)
);
this.timer = setInterval(() => this.render(), 1000);and :
this.timer = setInterval(this.render, 1000);let date = new Date();
let time = [date.getHours(), date.getMinutes(), date.getSeconds()];
let [hour, mins, secs] = time.map(item => item < 10 ? '0' + item : item);
let hours = date.getHours();
if (hours < 10) hours = '0' + hours;
let mins = date.getMinutes();
if (mins < 10) mins = '0' + mins;
let secs = date.getSeconds();
if (secs < 10) secs = '0' + secs;
I can not see result
I was thinking, how to make some private methods and variables using this article: hope later I will learn how to create it more clearly using proper syntax, if no, then I can go with this one :D
class Clock {
output = `${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()}`;
constructor({ template }) {
this._template = template;
}
render() {
let date = new Date();
let hours = date.getHours();
if (hours < 10) hours = "0" + hours;
let mins = date.getMinutes();
if (mins < 10) mins = "0" + mins;
let secs = date.getSeconds();
if (secs < 10) secs = "0" + secs;
let output = this._template
.replace("h", hours)
.replace("m", mins)
.replace("s", secs);
this.output = output;
console.log(output);
}
start() {
setInterval(this.render.bind(this), 1000);
}
}
let clock = new Clock({ template: "h:m:s" });
clock.start();
output = `${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()}`;
this._template = template;
}
let date = new Date();
if (hours < 10) hours = "0" + hours;
if (mins < 10) mins = "0" + mins;
if (secs < 10) secs = "0" + secs;
.replace("h", hours)
.replace("m", mins)
.replace("s", secs);
console.log(output);
}
setInterval(this.render.bind(this), 1000);
}
}
clock.start();
```
class Clock {
constructor(template = 'h:m:s') {
this.template = template;
}
render = () => {
let date = new Date();
let hours = date.getHours();
let h = hours < 10 ? '0' + hours : hours;
let mins = date.getMinutes();
let m = mins < 10 ? '0' + mins : mins;
let secs = date.getSeconds();
let s = secs < 10 ? '0' + secs : secs;
let output = this.template
.replace('h', h)
.replace('m', m)
.replace('s', s);
console.log(output);
}
start() {
this.render();
this.timer = setInterval(this.render, 1000);
}
stop() {
clearInterval(this.timer);
}
}
let clock = new Clock();
clock.start();