revision:
ECMAScript 2015, also known as ES6, introduced JavaScript Classes. They encapsulate data with code to work on that data. Classes in JS are built on prototypes but also have some syntax and semantics that are unique to classes.
class ClassName { constructor() { ... } }
class ClassName { constructor() { ... } method_1() {...} method_2() {...} method_3() {...} }
Classes are in fact "special functions", and just as you can define function expressions and function declarations, a class can be defined in two ways: a class expression or a class declaration.
declaration
class Rectangle { constructor(height, width) { this.height = height; this.width = width; } }
expression: anonymous or with name
const Rectangle = class { constructor(height, width) { this.height = height; this.width = width; } }; const Rectangle = class Rectangle2 { constructor(height, width) { this.height = height; this.width = width; } };
Always add a method named constructor().
class Car { constructor(name, year) { this.name = name; this.year = year; } }
When you have a class, you can use the class to create objects. The constructor method is called automatically when a new object is created.
Examples
example: how to use a JavaScript Class.
<div class="spec"> <a id="demo"></a> </div> <script> class Car { constructor(name, year) { this.name = name; this.year = year; } } myCar = new Car("Ford", 2014); document.getElementById("demo").innerHTML = myCar.name + " " + myCar.year; </script>
It has to have the exact name "constructor"; it is executed automatically when a new object is created; it is used to initialize object properties.
If you do not define a constructor method, JavaScript will add an empty constructor method.
Examples
example: pass a parameter into the "age()" method.
<div class="spec"> <a id="demo2"></a> </div> <script> class Car1 { constructor(name, year) { this.name = name; this.year = year; } age(x) { return x - this.year; } } let date = new Date(); let year = date.getFullYear(); let myCar = new Car1("Ford", 2014); document.getElementById("demo2").innerHTML = "my car is " + myCar.age(year) + " years old."; </script>
You will get an error if you do not follow the "strict mode" rules.
Examples
example: in a JavaScript class you cannot use variable without declaring it.
<div class="spec"> <a id="demo3"></a> </div> <script> class Car2 { constructor(name, year) { this.name = name; this.year = year; } age() { //date1 = new Date(); // This will not work let date1 = new Date(); // This will work return date1.getFullYear() - this.year; } } myCar = new Car2("Ford", 2013); document.getElementById("demo3").innerHTML = "My car is " + myCar.age() + " years old."; </script>
This is where you define class members, such as methods or constructor. The body of a class is executed in strict mode even without the "use strict" directive.
A class element can be characterized by three aspects:
Kind: getter, setter, method, or field;
location: static or instance;
Visibility: public or private
Together, they add up to 16 possible combinations. To divide the reference more logically and avoid overlapping content, the different elements are introduced as follows:
Method definitions: public instance method;
getter: public instance getter;
setter: public instance setter;
Public class fields: public instance field;
static: public static method, getter, setter, and field;
Private class features: everything that's private.
Note: Private features have the restriction that all property names declared in the same class must be unique. All other public properties do not have this restriction — you can have multiple public properties with the same name, and the last one overwrites the others. This is the same behavior as in object initializers.
In addition, there are two special class element syntaxes: constructor and static initialization blocks, with their own references.
Examples
<div> <p id="class1"></p> </div> <script> class ClassWithPublicInstanceMethod { publicMethod() { return "hello world"; } } const instance = new ClassWithPublicInstanceMethod(); console.log(instance.publicMethod()); // "hello world" document.getElementById("class1").innerHTML = instance.publicMethod(); </script>
Public instance methods are defined on the prototype property of the class and are thus shared by all instances of the class. They are writable, non-enumerable, and configurable.
Inside instance methods, this and super work like in normal methods. Usually, this refers to the instance itself.
In subclasses, super lets you access the prototype of the object that the method is attached to, allowing you to call methods from the superclass.
Examples
<div> <p id="class2"></p> </div> <script> class BaseClass { msg = "hello world"; basePublicMethod() { return this.msg; } } class SubClass extends BaseClass { subPublicMethod() { return super.basePublicMethod(); } } const instance2 = new SubClass(); console.log(instance2.subPublicMethod()); // "hello world" document.getElementById("class2").innerHTML = instance2.subPublicMethod(); </script>
examples
<div> <p id="class3"></p> <p id="class4"></p> </div> <script> class ClassWithGetSet { #msg = "hello world"; get msg() { return this.#msg; } set msg(x) { this.#msg = `hello ${x}`; } } const instance3 = new ClassWithGetSet(); console.log(instance3.msg); // "hello world" document.getElementById("class3").innerHTML = instance3. msg instance3.msg = "cake"; console.log(instance3.msg); // "hello cake" document.getElementById("class4").innerHTML = instance3. msg </script>
Getter properties are defined on the prototype property of the class and are thus shared by all instances of the class. Unlike getter properties in object literals, getter properties in classes are not enumerable.
Examples
<div> <p id="class5"></p> <p id="class6"></p> </div> <script> class ClassWithGetSet2 { #msg = "hello world"; get msg() { return this.#msg; } set msg(x) { this.#msg = `hello ${x}`; } } const instance4 = new ClassWithGetSet2(); console.log(instance4.msg); // "hello world" document.getElementById("class5").innerHTML = instance4. msg instance4.msg = "porto"; console.log(instance4.msg); // "hello cake" document.getElementById("class6").innerHTML = instance4. msg
Setter properties are defined on the prototype property of the class and are thus shared by all instances of the class. Unlike setter properties in object literals, setter properties in classes are not enumerable.
Examples
<div> <p id="class7"></p> <p id="class8"></p> <p id="class9"></p> <p id="class10"></p> <p id="class11"></p> <p id="class12"></p> <p id="class13"></p> <p id="class14"></p> </div> <script> class Triple { static customName = "Tripler"; static description = "I triple any number you provide"; static calculate(n = 1) { return n * 3; } } class SquaredTriple extends Triple { static longDescription; static description = "I square the triple of any number you provide"; static calculate(n) { return super.calculate(n) * super.calculate(n); } } console.log(Triple.description); // 'I triple any number you provide' document.getElementById("class7").innerHTML = Triple.description; console.log(Triple.calculate()); // 3 document.getElementById("class8").innerHTML = Triple.calculate(); console.log(Triple.calculate(6)); // 18 document.getElementById("class9").innerHTML = Triple.calculate(6); const tp = new Triple(); console.log(SquaredTriple.calculate(3)); // 81 (not affected by parent's instantiation) document.getElementById("class10").innerHTML = SquaredTriple.calculate(3); console.log(SquaredTriple.description); // 'I square the triple of any number you provide' document.getElementById("class11").innerHTML = SquaredTriple.description; console.log(SquaredTriple.longDescription); // undefined document.getElementById("class12").innerHTML = SquaredTriple.longDescription; console.log(SquaredTriple.customName); // 'Tripler' document.getElementById("class13").innerHTML = SquaredTriple.customName; // This throws because calculate() is a static member, not an instance member. console.log(tp.calculate()); // 'tp.calculate is not a function' document.getElementById("class14").innerHTML = tp.calculate();
Class fields are public by default, but private class members can be created by using a hash # prefix. The privacy encapsulation of these class features is enforced by JavaScript itself.
Private members are not native to the language before this syntax existed. In prototypical inheritance, its behavior may be emulated with WeakMap objects or closures, but they can't compare to the # syntax in terms of ergonomics.
Syntax:
class ClassWithPrivate { #privateField; #privateFieldWithInitializer = 42; #privateMethod() { // … } static #privateStaticField; static #privateStaticFieldWithInitializer = 42; static #privateStaticMethod() { // … } }
There are some additional syntax restrictions:
All private identifiers declared within a class must be unique. The namespace is shared between static and instance properties. The only exception is when the two declarations define a getter-setter pair.
The private identifier cannot be #constructor.
Examples
<div> <p id="class15"></p><br> <p id="class16"></p> </div> <script> class ClassWithPrivateStaticField { static #PRIVATE_STATIC_FIELD; static publicStaticMethod() { ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42; return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD; } publicInstanceMethod() { ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42; return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD; } } console.log(ClassWithPrivateStaticField.publicStaticMethod()); // 42 document.getElementById("class15").innerHTML = ClassWithPrivateStaticField.publicStaticMethod(); console.log(new ClassWithPrivateStaticField().publicInstanceMethod()); // 42 document.getElementById("class16").innerHTML = new ClassWithPrivateStaticField.publicStaticMethod(); </script>
A class created with a class inheritance inherits all the methods from another class. Inheritance is useful for code reusability: reuse properties and methods of an existing class when you create a new class.
Examples
example: use the "extends" keyword to inherit all methods from another class.
<div class="spec"> <p>use the <b>"super" method</b> to call the parent's constructor function.</p> <a id="demo4"></a> </div> <script> class Car3 { constructor(brand) { this.carname = brand; } present() { return 'I have a ' + this.carname; } } class Model extends Car3 { constructor(brand, mod) { super(brand); this.model = mod; } show() { return this.present() + ', it is a ' + this.model; } } let myCar2 = new Model("Ford", "Mustang"); document.getElementById("demo4").innerHTML = myCar2.show(); </script>
It can be smart to use "getters" and "setters" for your properties, especially if you want to do something special with the value before returning them, or before you set them. To add getters and setters in the class, use the "get" and "set" keywords.
Note: even if the getter is a method, you do not use parentheses when you want to get the property value.
Examples
example: a demonstration of how to add getters and setters in a class, and how to use the getter to get the property value.
<div class="spec"> <a id="demo5"></a> </div> <script> class Car4 { constructor(brand) { this.carname1 = brand; } get cnam() { return this.carname1; } set cnam(x) { this.carname1 = x; } } let myCar3 = new Car4("Ford"); document.getElementById("demo5").innerHTML = myCar3.cnam; </script>
The name of the getter/setter method cannot be the same as the name of the property , in this case carname. Many programmers use an underscore character ("_") before the property name to separate the getter/setter from the actual property.
That means that you must declare a class before you can use it.
Examples
example: you will get an error if you try to use a class before it is declared.
<div class="spec"> <a id="demo6"></a> </div> <script> //You cannot use the class yet. //myCar = new Car("Ford") //This would raise an error. class Car5 { constructor(brand) { this.carname2 = brand; } } //Now you can use the class: let myCar4 = new Car5("Ford") document.getElementById("demo6").innerHTML = myCar4.carname2; </script>
Static class methods are defined on the class itself. You cannot call a "static" method on an object, only on an object class.
Examples
example: a static method is created with the "static" keyword, and you can only call the method on the class itself.
<div class="spec"> <a id="demo7"></a> </div> <script> class Car6 { constructor(name) { this.name = name; } static hello() { return "Hello!!"; } } let myCar5 = new Car6("Ford"); //You can call 'hello()' on the Car Class: document.getElementById("demo7").innerHTML = Car6.hello(); // But NOT on a Car Object: // document.getElementById("demo7A").innerHTML = myCar5.hello(); // this will raise an error. </script>
the DOM
lorem error ipsum
lorem success ipsum
lorem success ipsum
lorem ipsum lorem
lorem ipsum success
error lorem ipsum
lorem ipsum lorem
lorem ipsum error
success lorem ipsum
<div> <p class="par">lorem error ipsum</p> <p class="par">lorem success ipsum</p> <p class="par">lorem success ipsum</p> <p class="par">lorem ipsum lorem</p> <p class="par">lorem ipsum success</p> <p class="par">error lorem ipsum</p> <p class="par">lorem ipsum lorem</p> <p class="par">lorem ipsum error</p> <p class="par">success lorem ipsum</p> </div> <style> .error {margin: 1rem; padding: 0.5rem; border: 3px dotted red; background: salmon; text-align: center; text-transform: uppercase;} .success {margin: 1rem; padding: 0.5rem; border: 3px solid green; background: seagreen; color: #fff; text-transform: capitalize; text-align: center;} .normal {margin: 1rem; padding: 0.5rem; border: 3px solid #000; text-transform: capitalize; text-align: center;} </style> <script> window.onload = function(){ const parag = document.querySelectorAll(".par"); const h4 = document.querySelector("h4"); parag.forEach(par =>{ if (par.textContent.includes("error")) { par.classList.add("error"); } else if (par.textContent.includes("success")) { par.classList.add("success"); } else { par.classList.add("normal"); } }); h4.classList.toggle("test"); }; // window.onload </script>
class Polygon { constructor() { this.name = 'Polygon'; } } const poly1 = new Polygon(); console.log(poly1.name); // expected output: "Polygon"
class DateFormatter extends Date { getFormattedDate() { const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; return `${this.getDate()}-${months[this.getMonth()]}-${this.getFullYear()}`; } } console.log(new DateFormatter('August 19, 1975 23:15:30').getFormattedDate()); // expected output: "19-Aug-1975"
class ClassWithStaticMethod { static staticMethod() { return 'static method has been called.'; } } console.log(ClassWithStaticMethod.staticMethod()) // expected output: "static method has been called."
function User(name) { this.name = name; this.isAdmin = false; } let user = new User("Jack"); alert(user.name); // Jack alert(user.isAdmin); // false
function User() { alert(new.target); } // without "new": User(); // undefined // with "new": new User(); // function User { ... } function User(name) { if (!new.target) { // if you run me without new return new User(name); // ...I will add new for you } this.name = name; } let john = User("John"); // redirects call to new User alert(john.name); // John
function BigUser() { this.name = "John"; return { name: "Godzilla" }; // <-- returns this object } alert( new BigUser().name ); // Godzilla, got that object function SmallUser() { this.name = "John"; return; // <-- returns this } alert( new SmallUser().name ); // John
function User(name) { this.name = name; this.sayHi = function() { alert( "My name is: " + this.name ); }; } let john = new User("John"); john.sayHi(); // My name is: John /* john = { name: "John", sayHi: function() { ... } } */