Cara menggunakan parent keyword in javascript

The function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 5 keyword is used in class declarations or class expressions to create a class that is a child of another class.

class ChildClass extends ParentClass { /* … */ }

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 6

An expression that evaluates to a constructor function (including a class) or function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 7.

The function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 5 keyword can be used to subclass custom classes as well as built-in objects.

Any constructor that can be called with function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 9 and has the function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number! 0 property can be the candidate for the parent class. The two conditions must both hold — for example, bound functions and function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number! 1 can be constructed, but they don't have a function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number! 0 property, so they cannot be subclassed.

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {}

The function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number! 0 property of the function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 6 must be an function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number! 5 or function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 7, but you would rarely worry about this in practice, because a non-object function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number! 0 doesn't behave as it should anyway. (It's ignored by the function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 9 operator.)

function ParentClass() {} ParentClass.prototype = 3; class ChildClass extends ParentClass {} // Uncaught TypeError: Class extends value does not have valid prototype property 3 console.log(Object.getPrototypeOf(new ParentClass())); // [Object: null prototype] {} // Not actually a number!

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 5 sets the prototype for both class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 0 and class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 1.

Prototype of class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 0Prototype of class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 1function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 5 clause absentclass ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 5class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 6class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 7class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype; 5function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 7class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 0function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 6class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 2

class ParentClass {} class ChildClass extends ParentClass {} // Allows inheritance of static properties Object.getPrototypeOf(ChildClass) === ParentClass; // Allows inheritance of instance properties Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype;

The right-hand side of function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 5 does not have to be an identifier. You can use any expression that evaluates to a constructor. This is often useful to create .

class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class

While the base class may return anything from its constructor, the derived class must return an object or class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 4, or a class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 5 will be thrown.

class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined

If the parent class constructor returns an object, that object will be used as the class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 6 value for the derived class when further initializing class fields. This trick is called , which allows a derived class's fields (including private ones) to be defined on unrelated objects.

Warning: The standard committee now holds the position that the built-in subclassing mechanism in previous spec versions is over-engineered and causes non-negligible performance and security impacts. New built-in methods consider less about subclasses, and engine implementers are investigating whether to remove certain subclassing mechanisms. Consider using composition instead of inheritance when enhancing built-ins.

Here are some things you may expect when extending a class:

  • When calling a static factory method (like class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 7 or class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 8) on a subclass, the returned instance is always an instance of the subclass.
  • When calling an instance method that returns a new instance (like class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 9 or class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 0) on a subclass, the returned instance is always an instance of the subclass.
  • Instance methods try to delegate to a minimal set of primitive methods where possible. For example, for a subclass of class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 1, overriding class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 2 automatically causes the behavior of class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 3 to change; or for a subclass of class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 4, overriding class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 5 automatically causes the behavior of the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 6 constructor to change.

However, the above expectations take non-trivial efforts to implement properly.

  • The first one requires the static method to read the value of class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 6 to get the constructor for constructing the returned instance. This means class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 8 throws an error because the class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 6 inside class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } } 0 is class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 4. A way to fix this is to fall back to the base class if class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 6 is not a constructor, like class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 8 does, but that still means the base class is special-cased.
  • The second one requires the instance method to read class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } } 4 to get the constructor function. However, class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } } 5 may break legacy code, because the class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } } 6 property is both writable and configurable and is not protected in any way. Therefore, many copying built-in methods use the constructor's class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } } 7 property instead (which by default just returns class SomeClass extends class { constructor() { console.log("Base class"); } } { constructor() { super(); console.log("Derived class"); } } new SomeClass(); // Base class // Derived class 6, the constructor itself). However, class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } } 7 allows running arbitrary code and creating instances of arbitrary type, which poses a security concern and greatly complicates subclassing semantics.
  • The third one leads to visible invocations of custom code, which makes a lot of optimizations harder to implement. For example, if the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 6 constructor is called with an iterable of x elements, then it must visibly invoke the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 5 method x times, instead of just copying the elements into the internal storage.

These problems are not unique to built-in classes. For your own classes, you will likely have to make the same decisions. However, for built-in classes, optimizability and security are a much bigger concern. New built-in methods always construct the base class and call as few custom methods as possible. If you want to subclass built-ins while achieving the above expectations, you need to override all methods that have the default behavior baked into them. Any addition of new methods on the base class may also break the semantics of your subclass because they are inherited by default. Therefore, a better way to extend built-ins is to use .

The first example creates a class called const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 2 from a class called const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 3. This example is extracted from this live demo (source).

class Square extends Polygon { constructor(length) { // Here, it calls the parent class' constructor with lengths // provided for the Polygon's width and height super(length, length); // Note: In derived classes, super() must be called before you // can use 'this'. Leaving this out will cause a reference error. this.name = 'Square'; } get area() { return this.height * this.width; } }

Classes cannot extend regular (non-constructible) objects. If you want to inherit from a regular object by making all properties of this object available on inherited instances, you can instead use const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 4:

const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise.

This example extends the built-in const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 5 object. This example is extracted from this live demo (source).

class MyDate 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()}`; } }

You might want to return const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 6 objects in your derived array class const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 7. The species pattern lets you override default constructors.

For example, when using methods such as class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 0 that return the default constructor, you want these methods to return a parent const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 6 object, instead of the const Animal = { speak() { console.log(`${this.name} makes a noise.`); } }; class Dog { constructor(name) { this.name = name; } } Object.setPrototypeOf(Dog.prototype, Animal); const d = new Dog("Mitzie"); d.speak(); // Mitzie makes a noise. 7 object. The class MyDate 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()}`; } } 1 symbol lets you do this:

class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { return Array; } } const a = new MyArray(1, 2, 3); const mapped = a.map((x) => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true

This behavior is implemented by many built-in copying methods. For caveats of this feature, see the discussion.

Abstract subclasses or mix-ins are templates for classes. A class can only have a single superclass, so multiple inheritance from tooling classes, for example, is not possible. The functionality must be provided by the superclass.

A function with a superclass as input and a subclass extending that superclass as output can be used to implement mix-ins:

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 0

A class that uses these mix-ins can then be written like this:

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 1

Inheritance is a very strong coupling relationship in object-oriented programming. It means all behaviors of the base class are inherited by the subclass by default, which may not always be what you want. For example, consider the implementation of a class MyDate 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()}`; } } 2:

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 2

It turns out that class MyDate 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()}`; } } 2 is not constructible, because the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 6 constructor calls the instance's class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 5 method.

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 3

We may get around this by using a private flag to indicate whether the instance is being constructed. However, a more significant problem with this design is that it breaks the Liskov substitution principle, which states that a subclass should be substitutable for its superclass. If a function expects a class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 4 object, it should be able to use a class MyDate 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()}`; } } 2 object as well, which will break here.

Inheritance often leads to the circle-ellipse problem, because neither type perfectly entails the behavior of the other, although they share a lot of common traits. In general, unless there's a very good reason to use inheritance, it's better to use composition instead. Composition means that a class has a reference to an object of another class, and only uses that object as an implementation detail.

function OldStyleClass() { this.someProperty = 1; } OldStyleClass.prototype.someMethod = function () {}; class ChildClass extends OldStyleClass {} class ModernClass { someProperty = 1; someMethod() {} } class AnotherChildClass extends ModernClass {} 4

In this case, the class MyDate 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()}`; } } 2 class is not a subclass of class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 4, but it still implements most of the same methods. This means more code duplication, but it also means that the class MyDate 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()}`; } } 2 class is not strongly coupled to the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 4 class, and does not easily break if the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 4 class is changed, avoiding the . For example, if the class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 4 class adds an class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { return Array; } } const a = new MyArray(1, 2, 3); const mapped = a.map((x) => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true 4 method that does not call class ParentClass { constructor() { return 1; } } console.log(new ParentClass()); // ParentClass {} // The return value is ignored because it's not an object // This is consistent with function constructors class ChildClass extends ParentClass { constructor() { return 1; } } console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined 5, it would cause the class MyDate 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()}`; } } 2 class to no longer be read-only unless the latter is updated accordingly to override class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { return Array; } } const a = new MyArray(1, 2, 3); const mapped = a.map((x) => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true 4 as well. Moreover, class MyDate 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()}`; } } 2 objects do not have the class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { return Array; } } const a = new MyArray(1, 2, 3); const mapped = a.map((x) => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true 9 method at all, which is more accurate than throwing an error at runtime.

Apa yang dimaksud dengan parent class dan child class?

Suatu class yang mempunyai class turunan dinamakan parent class atau base class. Sedangkan class turunan itu sendiri seringkali disebut subclass atau child class.

Apa itu child class?

Class yang akan 'diturunkan' bisa disebut sebagai class induk (parent class), super class, atau base class. Sedangkan class yang 'menerima penurunan' bisa disebut sebagai class anak (child class), sub class, derived class atauheir class.

Postingan terbaru

LIHAT SEMUA