Gordon  Murray

Gordon Murray

1669718160

Deploy Apps More Efficiently with MongoDB Atlas Serverless instances

If you’re a developer, worrying about your database is not necessarily something you want to do. You likely don’t want to spend your time provisioning or sizing clusters as the demand of your application changes. You probably also don’t want to worry about breaking the bank if you’ve scaled something incorrectly.

With MongoDB Atlas, you have a few deployment options to choose from when it comes to your database. While you could choose a pre-provisioned shared or dedicated cluster, you’re still stuck having to size and estimate the database resources you will need and subsequently managing your cluster capacity to best fit demand. While a pre-provisioned cluster isn’t necessarily a bad thing, it might not make sense if your development becomes idle or you’re expecting frequent periods of growth or decline. Instead, you can opt for a serverless instance to help remove the capacity management burden and free up time to dedicate to writing code. Serverless instances provide an on-demand database endpoint for your application that will automatically scale up and down to zero with application demand and only charge you based on your usage.

In this short and sweet tutorial, we’ll see how easy it is to get started with a MongoDB Atlas serverless instance and how to begin to develop an application against it.

Deploy a MongoDB Atlas serverless instance

We’re going to start by deploying a new MongoDB Atlas serverless instance. There are numerous ways to accomplish deploying MongoDB, but for this example, we’ll stick to the web dashboard and some point and click.

From the MongoDB Atlas dashboard, click the “Create” button.

MongoDB Atlas Serverless Instance

Choose “Serverless” as well as a cloud vendor where this instance should live.

If possible, choose a cloud vendor that matches where your application will live. This will give you the best possible latency between your database and your application.

Once you choose to click the “Create Instance” button, your instance is ready to go!

You’re not in the clear yet though. You won’t be able to use your Atlas serverless instance outside of the web dashboard until you create some database access and network access rules.

We’ll start with a new database user.

Atlas Serverless Instance Database Access

Choose the type of authentication that makes the most sense for you. To keep things simple for this tutorial, I recommend choosing the “Password” option.

While you could use a “Built-in Role” when it comes to user privileges, your best bet for any application is to define “Specific Privileges” depending on what the user should be allowed to do. For this project, we’ll be using an “example” database and a “people” collection, so it makes sense to give only that database and collection readWrite access.

Use your best judgment when creating users and defining access.

With a user created, we can move onto the network access side of things. The final step before we can start developing against our database.

Atlas Serverless Instance Network Access

In the “Network Access” tab, add the IP addresses that should be allowed access. If you’re developing and testing locally like I am, just add your local IP address. Just remember to add the IP range for your servers or cloud vendor when the time comes. You can also take advantage of private networking if needed.

With the database and network access out of the way, let’s grab the URI string that we’ll be using in the next step of the tutorial.

From the Database tab, click the “Connect” button for your serverless instance.

Atlas Serverless Instance Connection URI

Choose the programming language you wish to use and make note of the URI.

Need more help getting started with serverless instances? Check out this video that can walk you through it.

Interacting with an Atlas serverless instance using a popular programming technology

At this point, you should have an Atlas serverless instance deployed. We’re going to take a moment to connect to it from application code and do some interactions, such as basic CRUD.

For this particular example, we’ll use JavaScript with the MongoDB Node.js driver, but the same rules and concepts apply, minus the language differences for the programming language that you wish to use.

On your local computer, create a project directory and navigate into it with your command line. You’ll want to execute the following commands once it becomes your working directory:

npm init -y
npm install mongodb
touch main.js

With the above commands, we’ve initialized a Node.js project, installed the MongoDB Node.js driver, and created a main.js file to contain our code.

Open the main.js file and add the following JavaScript code:

const { MongoClient } = require("mongodb");

const mongoClient = new MongoClient("MONGODB_URI_HERE");

(async () => {
    try {
        await mongoClient.connect();
        const database = mongoClient.db("example");
        const collection = database.collection("people");
        const inserted = await collection.insertOne({
            "firstname": "Nic",
            "lastname": "Raboy",
            "location": "California, USA"
        });
        const found = await collection.find({ "lastname": "Raboy" }).toArray();
        console.log(found);
        const deleted = await collection.deleteMany({ "lastname": "Raboy" });
    } catch (error) {
        console.error(error);
    } finally {
        mongoClient.close();
    }
})();

So, what’s happening in the above code?

First, we define our client with the URI string for our serverless instance. This is the same string that you took note of earlier in the tutorial and it should contain a username and password.

With the client, we can establish a connection and get a reference to a database and collection that we want to use. The database and collection does not need to exist prior to running your application.

Next, we are doing three different operations with the MongoDB Query API. First, we are inserting a new document into our collection. After the insert is complete, assuming our try/catch block didn’t find an error, we find all documents where the lastname matches. For this example, there should only ever be one document, but you never know what your code looks like. If a document was found, it will be printed to the console. Finally, we are deleting any document where the lastname matches.

By the end of this, no documents should exist in your collection, assuming you are following along with my example. However, a document did (at some point in time) exist in your collection — we just deleted it.

Alright, so we have a basic example of how to build an application around an on-demand database, but it didn’t really highlight the benefit of why you’d want to. So, what can we do about that?

Pushing an Atlas serverless instance with a plausible application scenario

We know that pre-provisioned and serverless clusters work well and from a development perspective, you’re going to end up with the same results using the same code.

Let’s come up with a scenario where a serverless instance in Atlas might lower your development costs and reduce the scaling burden to match demand. Let’s say that you have an online store, but not just any kind of online store. This online store sees mild traffic most of the time and a 1000% spike in traffic every Friday between the hours of 9AM and 12PM because of a lightning type deal that you run.

We’ll leave mild traffic up to your imagination, but a 1000% bump is nothing small and would likely require some kind of scaling intervention every Friday on a pre-provisioned cluster. That, or you’d need to pay for a larger sized database.

Let’s visualize this example with the following Node.js code:

const { MongoClient } = require("mongodb");
const Express = require("express");
const BodyParser = require("body-parser");

const app = Express();

app.use(BodyParser.json());

const mongoClient = new MongoClient("MONGODB_URI_HERE");
var database, purchasesCollection, dealsCollection;

app.get("/deal", async (request, response) => {
    try {
        const deal = await dealsCollection.findOne({ "date": "2022-10-07" });
        response.send(deal || {});
    } catch (error) {
        response.status(500).send({ "message": error.message });
    }
});

app.post("/purchase", async (request, response) => {
    try {
        if(!request.body) {
            throw { "message": "The request body is missing!" };
        }
        const receipt = await purchasesCollection.insertOne(
            { 
                "sku": (request.body.sku || "000000"),
                "product_name": (request.body.product_name || "Pokemon Scarlet"),
                "price": (request.body.price || 59.99),
                "customer_name": (request.body.customer_name || "Nic Raboy"),
                "purchase_date": "2022-10-07"
            }
        );
        response.send(receipt || {});
    } catch (error) {
        response.status(500).send({ "message": error.message });
    }
});

app.listen(3000, async () => {
    try {
        await mongoClient.connect();
        database = mongoClient.db("example");
        dealsCollection = database.collection("deals");
        purchasesCollection = database.collection("receipts");
        console.log("SERVING AT :3000...");
    } catch (error) {
        console.error(error);
    }
});

In the above example, we have an Express Framework-powered web application with two endpoint functions. We have an endpoint for getting the deal and we have an endpoint for creating a purchase. The rest can be left up to your imagination.

To load test this application with bursts and simulate the potential value of a serverless instance, we can use a tool like Apache JMeter.

With JMeter, you can define the number of threads and iterations it uses when making HTTP requests.

JMeter Thread Group

Remember, we’re simulating a burst in this example. If you do decide to play around with JMeter and you go excessive on the burst, you could end up with an interesting bill. If you’re interested to know how serverless is billed, check out the pricing page in the documentation.

JMeter HTTP Request

Inside your JMeter Thread Group, you’ll want to define what is happening for each thread or iteration. In this case, we’re doing an HTTP request to our Node.js API.

Since the API expects JSON, we can define the header information for the request.

jmeter_http_header

Once you have the thread information, the HTTP request information, and the header information, you can run JMeter and you’ll end up with a lot of activity against not only your web application, but also your database.

Again, a lot of this example has to be left to your imagination because to see the scaling benefits of a serverless instance, you’re going to need a lot of burst traffic that isn’t easily simulated during development. However, it should leave you with some ideas.

Conclusion

You just saw how quick it is to develop on MongoDB Atlas without having to burden yourself with sizing your own cluster. With a MongoDB Atlas serverless instance, your database will scale to meet the demand of your application and you’ll be billed for that demand. This will protect you from paying for improperly sized clusters that are running non-stop. It will also save you the time you would have spent making size related adjustments to your cluster.

The code in this example works regardless if you are using an Atlas serverless instance or a pre-provisioned shared or dedicated cluster.

Got a question regarding this example, or want to see more? Check out the MongoDB Community Forums to see what’s happening.

Original article source at: https://www.thepolyglotdeveloper.com/

#mongodb #serverless #instances 

Deploy Apps More Efficiently with MongoDB Atlas Serverless instances
Desmond  Gerber

Desmond Gerber

1669620984

How to Use Gson To Serialize and Deserialize Kotlin Class instances

Using Gson library with Kotlin class and data class instances

The Gson library is a Java library developed by Google that allows you to serialize and deserialize Java objects to their JSON representation.

The library can also be used in Kotlin to convert Kotlin class and data class instances into their JSON representations.

First, you need to add the Gson library as a dependency to your project. If you’re developing an Android application, you can add the dependency in your app/build.gradle file:

dependencies {
    implementation 'androidx.core:core-ktx:1.7.0'
    // ...
    implementation 'com.google.code.gson:gson:2.8.9'
}

Or if you’re developing a Kotlin app with Maven, add the following to your pom.xml file <dependencies> tag:

<dependency>
  <groupId>com.google.code.gson</groupId>
  <artifactId>gson</artifactId>
  <version>2.8.9</version>
</dependency>

Once you sync the dependencies for your project, the Gson library should be available for you to use.

Convert Kotlin class into JSON format with Gson

To convert a Kotlin class instance into its JSON instance, you need to call the Gson().toJson() method and pass the class instance as its parameter.

Suppose you have a User data class with the following definition:

data class User(
    val firstName: String, 
    val lastName: String
)

You can create a JSON representation of the User data class instance as follows:

val myUser = User("Nathan", "Sebhastian")

val jsonString = Gson().toJson(myUser)
println(jsonString)

The jsonString variable value would be as follows:

{"firstName":"Nathan","lastName":"Sebhastian"}

Both Kotlin class and data class instances can be serialized in the same way.

Convert JSON into Kotlin class format

Gson can also be used to convert a JSON string back into Kotlin class instance by calling the fromJson() method.

The following example takes the userJson string and converts it into a Kotlin object:

val userJson = """
{ 
    "firstName": "Arya", 
    "lastName": "Stark"
}"""

val myUser = Gson().fromJson(userJson, User::class.java)

println(myUser.firstName) // Arya
println(myUser.lastName) // Stark

The fromJson() method accepts two parameters:

  • The first is the JSON string to convert to an object
  • The second is the class to be used as the object blueprint

And that’s how you deserialize a JSON string using the Gson library.

Adding custom JSON key to Kotlin class

By default, Gson will use the class field names for your JSON keys.

You can define custom JSON keys for each of your field names using the @SerializedName annotation as follows:

data class User(
    @SerializedName("first_name")
    val firstName: String,
    @SerializedName("last_name")
    val lastName: String
)

When you call the toJson() method, the JSON keys will use the annotations as shown below:

val myUser = User("Nathan", "Sebhastian")

val jsonString = Gson().toJson(myUser)

println(jsonString)
// {"first_name":"Nathan","last_name":"Sebhastian"}

The same goes when you call the fromJson() method.

And that’s how you can use the Gson library with Kotlin class instances.

When the only purpose of your Kotlin class is to provide a blueprint for JSON values, it’s recommended to create a data class instead of a regular class.

Learn more about Kotlin data class here.

Original article source at: https://sebhastian.com/

#kotlin #class #instances 

How to Use Gson To Serialize and Deserialize Kotlin Class instances

Constructor Function, Prototype & Classes in JavaScript

In this video we will learn:
Add primitive properties to constructor function using #prototype and how they behave in #instances
Add non-primitive properties i.e. array to constructor function using #prototype and how they behave in instances
How to create classes and subclasses?
How to create and use class methods in JavaScript?
What are static methods in javaScript Classes?
How to create and use static methods?
How to use parent classes Methods in subclass / Child class in JavaScript?

#es6   #javascript 

 

 Constructor Function, Prototype & Classes in JavaScript
Kiera Smart

Kiera Smart

1584696569

Everything you should know about JavaScript Classes

Class in Javascript is a type of function, but instead of initializing it with the function keyword, the class keyword is used. This post familiarizes you with JavaScript classes: how to define a class, initialize the instance, define fields and methods, understand the private and public fields, grasp the static fields and methods.

Classes are a fundamental concept in object-oriented programming, and they are used in many programming languages, but it wasn’t like this in Javascript. Until ECMAScript2015, known as ES6, classes didn’t exist in JS. In 2015 with the update classes were introduced as syntactic sugar for the existing prototype inheritance model. What classes bring is a more comfortable and more readable syntax for objects and inheritance.

Table of Contents

1. Definition: class keyword

2. Initialization: constructor()

3. Fields

  • 3.1 Public instance fields
  • 3.2 Private instance fields
  • 3.3 Public static fields
  • 3.4 Private static fields

4. Methods

  • 4.1 Instance methods
  • 4.2 Getters and setters
  • 4.3 Static methods

5. Inheritance: extends

  • 5.1 Parent constructor: super() in constructor()
  • 5.2 Parent instance: super in methods

6. Object type checking: instanceof

7. Classes and prototypes

8. Class features availability

9. Conclusion


The Complete Guide to JavaScript Classes

1. Definition: class keyword

The special keyword class defines a class in JavaScript:

class User {
  // The body of class
}

The code above defines a class User. The curly braces { } delimit the class body. Note that this syntax is named class declaration.

You’re not obligated to indicate the class name. By using a class expression you can assign the class to a variable:

const UserClass = class {
  // The body of class
};

You can easily export a class as part of an ES2015 module. Here’s the syntax for a default export:

export default class User {
 // The body of class
}

And a named export:

export class User {
  // The body of class
}

The class becomes useful when you create an instance of the class. An instance is an object containing data and behavior described by the class.
JavaScript class instances

The new operator instantiates the class in JavaScript: instance = new Class().

For example, you can instantiate the User class using the new operator:

const myUser = new User();

new User() creates an instance of the User class.

2. Initialization: constructor()

constructor(param1, param2, ...) is a special method in the body of a class that initializes the instance. That’s the place where you set the initial values for the fields, or do any kind of object setup.

In the following example the constructor sets the initial value of the field name:

class User {
  constructor(name) {    this.name = name;  }}

User’s constructor has one parameter name, which is used to set the initial value of the field this.name.

Inside the constructor this value equals to the newly created instance.

The arguments used to instantiate the class become the parameters of the constructor:

class User {
  constructor(name) {
    name; // => 'Jon Snow'    this.name = name;
  }
}

const user = new User('Jon Snow');

name parameter inside the constructor has the value 'Jon Snow'.

If you don’t define a constructor for the class, a default one is created. The default constructor is an empty function, which doesn’t modify the instance.

At the same time, a JavaScript class can have up to one constructor.

3. Fields

Class fields are variables that hold information. Fields can be attached to 2 entities:

  1. Fields on the class instance
  2. Fields on the class itself (aka static)

The fields also have 2 levels of accessibility:

  1. Public: the field is accessible anywhere
  2. Private: the field is accessible only within the body of the class

3.1 Public instance fields

Let’s look again at the previous code snippet:

class User {
  constructor(name) {
    this.name = name;  }
}

The expression this.name = name creates an instance field name and assigns to it an initial value.

Later you can access name field using a property accessor:

const user = new User('Jon Snow');
user.name; // => 'Jon Snow'

name is a public field because you can access it outside of the User class body.

When the fields are created implicitly inside the constructor, like in the previous scenario, it could be difficult to grasp the fields list. You have to decipher them from the constructor’s code.

A better approach is to explicitly declare the class fields. No matter what constructor does, the instance always has the same set of fields.

The class fields proposal lets you define the fields inside the body of the class. Plus, you can indicate the initial value right away:

class SomeClass {
  field1;  field2 = 'Initial value';
  // ...
}

Let’s modify the User class and declare a public field name:

class User {
  name;  
  constructor(name) {
    this.name = name;
  }
}

const user = new User('Jon Snow');
user.name; // => 'Jon Snow'

name; inside the body of the class declares a public field name.

The public fields declared such a way is expressive: a quick look at the fields declarations is enough to understand the class’s data structure.

Moreover, the class field can be initialized right away at declaration.

class User {
  name = 'Unknown';
  constructor() {
    // No initialization
  }
}

const user = new User();
user.name; // => 'Unknown'

name = 'Unknown' inside the class body declares a field name and initializes it with value 'Unknown'.

There’s no restriction on access or update of the public fields. You can read and assign values to public fields inside the constructor, methods, and outside of the class.

3.2 Private instance fields

Encapsulation is an important concept that lets you hide the internal details of a class. Someone that uses an encapsulated class depends only on the public interface that the class provides, and doesn’t couple to the implementation details of the class.

Classes organized with encapsulation in mind are easier to update when implementation details change.

A good way to hide internal data of an object is to use the private fields. These are the fields that can be read and change only within the class they belong to. The outside world of the class cannot change private fields directly.

The private fields are accessible only within the body of the class.

Prefix the field name with the special symbol # to make it private, e.g. #myField. The prefix # must be kept every time you work with the field: declare it, read it, or modify it.

Let’s make sure that the field #name can be set once at the instance initialization:

class User {
  #name;
  constructor(name) {
    this.#name = name;
  }

  getName() {
    return this.#name;
  }
}

const user = new User('Jon Snow');
user.getName(); // => 'Jon Snow'

user.#name;     // SyntaxError is thrown

#name is a private field. You can access and modify #name within the body of the User. The method getName() (more about methods in next section) can access the private field #name.

But if you try to access the private field #name outside of User class body, a syntax error is thrown: SyntaxError: Private field '#name' must be declared in an enclosing class.

3.3 Public static fields

You can also define fields on the class itself: the static fields. These are helpful to define class constants or store information specific to the class.

To create static fields in a JavaScript class, use the special keyword static followed by the field name: static myStaticField.

Let’s add a new field type that indicates the user type: admin or regular. The static fields TYPE_ADMIN and TYPE_REGULAR are handy constants to differentiate the user types:

class User {
  static TYPE_ADMIN = 'admin';  static TYPE_REGULAR = 'regular';
  name;
  type;

  constructor(name, type) {
    this.name = name;
    this.type = type;
  }
}

const admin = new User('Site Admin', User.TYPE_ADMIN);
admin.type === User.TYPE_ADMIN; // => true

static TYPE_ADMIN and static TYPE_REGULAR define static variables inside the User class. To access the static fields, you have to use the class followed by the field name: User.TYPE_ADMIN and User.TYPE_REGULAR.

3.4 Private static fields

Sometimes even the static fields are an implementation detail that you’d like to hide. In this regard, you can make static fields private.

To make the static field private, prefix the field name with # special symbol: static #myPrivateStaticField.

Let’s say you’d like to limit the number of instances of the User class. To hide the details about instances limits, you can create the private static fields:

class User {
  static #MAX_INSTANCES = 2;  static #instances = 0;  
  name;

  constructor(name) {
    User.#instances++;
    if (User.#instances > User.#MAX_INSTANCES) {
      throw new Error('Unable to create User instance');
    }
    this.name = name;
  }
}

new User('Jon Snow');
new User('Arya Stark');
new User('Sansa Stark'); // throws Error

The static field User.#MAX_INSTANCES sets the maximum number of allowed instances, while User.#instances static field counts the actual number of instances.

These private static fields are accessible only within the User class. Nothing from the external world can interfere with the limits mechanism: that’s the benefit of encapsulation.

4. Methods

The fields hold data. But the ability to modify data is performed by special functions that are a part of the class: the methods.

The JavaScript classes support both instance and static methods.

4.1 Instance methods

Instance methods can access and modify instance data. Instance methods can call other instance methods, as well as any static method.

For example, let’s define a method getName() that returns the name in the User class:

class User {
  name = 'Unknown';

  constructor(name) {
    this.name = name;
  }

  getName() {    return this.name;  }}

const user = new User('Jon Snow');
user.getName(); // => 'Jon Snow'

getName() { ... } is a method inside the User class. user.getName() is a method invocation: it executes the method and returns the computed value if any.

In a class method, as well as in the constructor, this value equals to the class instance. Use this to access instance data: this.field, or even call other methods: this.method().

Let’s add a new method nameContains(str) that has one parameter and calls another method:

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }

  nameContains(str) {    return this.getName().includes(str);  }}

const user = new User('Jon Snow');
user.nameContains('Jon');   // => true
user.nameContains('Stark'); // => false

nameContains(str) { ... } is a method of User class that accepts one parameter str. More than that, it executes another method of the instance this.getName() to get the user’s name.

A method can also be private. To make the method private prefix its name with #.

Let’s make getName() method private:

class User {
  #name;

  constructor(name) {
    this.#name = name;
  }

  #getName() {    return this.#name;  }
  nameContains(str) {
    return this.#getName().includes(str);  }
}

const user = new User('Jon Snow');
user.nameContains('Jon');   // => true
user.nameContains('Stark'); // => false

user.#getName(); // SyntaxError is thrown

#getName() is a private method. Inside the method nameContains(str) you call a private method such way: this.#getName().

Being private, #getName() cannot be called outside of User class body.

4.2 Getters and setters

The getter and setter mimic regular field, but with more control on how the field is accessed and changed.

The getter is executed on an attempt to get the field value, while setter on an attempt to set a value.

To make sure that the name property of the User cannot be empty, let’s wrap the private field #nameValue in a getter and setter:

class User {
  #nameValue;

  constructor(name) {
    this.name = name;
  }

  get name() {    return this.#nameValue;
  }

  set name(name) {    if (name === '') {
      throw new Error(`name field of User cannot be empty`);
    }
    this.#nameValue = name;
  }
}

const user = new User('Jon Snow');
user.name; // The getter is invoked, => 'Jon Snow'
user.name = 'Jon White'; // The setter is invoked

user.name = ''; // The setter throws an Error

get name() {...} getter is executed when you access the value of the field: user.name.

While set name(name) {...} is executed when the field is updated user.name = 'Jon White'. The setter throws an error if the new value is an empty string.

4.3 Static methods

The static methods are functions attached directly to the class. They hold logic related to the class, rather than to the instance of the class.

To create a static method use the special keyword static followed by a regular method syntax: static myStaticMethod() { ... }.

When working with static methods, there are 2 simple rules to remember:

  1. A static method can access static fields
  2. A static method cannot access instance fields.

For example, let’s create a static method that detects whether a user with a specific name was already taken.

class User {
  static #takenNames = [];

  static isNameTaken(name) {    return User.#takenNames.includes(name);  }
  name = 'Unknown';

  constructor(name) {
    this.name = name;
    User.#takenNames.push(name);
  }
}

const user = new User('Jon Snow');

User.isNameTaken('Jon Snow');   // => true
User.isNameTaken('Arya Stark'); // => false

isNameTaken() is a static method that uses the static private field User.#takenNames to check for taken names.

Static methods can be private: static #staticFunction() {...}. Again, they follow the rules of privacy: you can call a private static method only within the class body.

5. Inheritance: extends

The classes in JavaScript support single inheritance using the extends keyword.

In the expression class Child extends Parent { } the Child class inherits from Parent the constructor, fields, and methods.

For example, let’s create a new child class ContentWriter that extends the parent class User.

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {  posts = [];
}

const writer = new ContentWriter('John Smith');

writer.name;      // => 'John Smith'
writer.getName(); // => 'John Smith'
writer.posts;     // => []

ContentWriter inherits from the User the constructor, the method getName() and the field name. As well, the ContentWriter class declares a new field posts.

Note that private members of a parent class are not inherited by the child class.

5.1 Parent constructor: super() in constructor()

If you’d like to call the parent constructor in a child class, you need to use the super() special function available in the child constructor.

For example, let’s make ContentWriter constructor call the parent constructor of User, as well as initialize the posts field:

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);    this.posts = posts;
  }
}

const writer = new ContentWriter('John Smith', ['Why I like JS']);
writer.name; // => 'John Smith'
writer.posts // => ['Why I like JS']

super(name) inside the child class ContentWriter executes the constructor of the parent class User.

Note that inside the child constructor you must execute super() before using this keyword. Calling super() makes sure that the parent constructor initializes the instance.

class Child extends Parent {
  constructor(value1, value2) {
    // Does not work!
    this.prop2 = value2;    super(value1);  }
}

5.2 Parent instance: super in methods

If you’d like to access the parent method inside of a child method, you can use the special shortcut super.

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }

  getName() {
    const name = super.getName();    if (name === '') {
      return 'Unknwon';
    }
    return name;
  }
}

const writer = new ContentWriter('', ['Why I like JS']);
writer.getName(); // => 'Unknwon'

getName() of the child class ContentWriter accesses the method super.getName() directly from the parent class User.

This feature is called method overriding.

Note that you can use super with static methods too, to access the parent’s static methods.

6. Object type checking: instanceof

object instanceof Class is the operator that determines if object is an instance of Class.

Let’s see instanceof operator in action:

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('Jon Snow');
const obj = {};

user instanceof User; // => true
obj instanceof User; // => false

user is an instance of User class, user instanceof User evaluates to true.

The empty object {} is not an instance of User, correspondingly obj instanceof User is false.

instanceof is polymorphic: the operator detects a child as an instance of the parent class.

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }
}

const writer = new ContentWriter('John Smith', ['Why I like JS']);

writer instanceof ContentWriter; // => true
writer instanceof User;          // => true

writer is an instance of the child class ContentWriter. The operator writer instanceof ContentWriter evaluates to true.

At the same time ContentWriter is a child class of User. So writer instanceof User evaluates to true as well.

What if you’d like to determine the exact class of the instance? You can use the constructor property and compare directly with the class:

writer.constructor === ContentWriter; // => true
writer.constructor === User;          // => false

7. Classes and prototypes

I must say that the class syntax in JavaScript does a great job to abstract from the prototypal inheritance. To describe the class syntax I haven’t even used the term prototype.

But the classes are built on top of the prototypal inheritance. Every class is a function, and creates an instance when invoked as a constructor

The following two code snippets are equivalent.

The class version:

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('John');

user.getName();       // => 'John Snow'
user instanceof User; // => true

The version using prototype:

function User(name) {
  this.name = name;
}

User.prototype.getName = function() {
  return this.name;
}

const user = new User('John');

user.getName();       // => 'John Snow'
user instanceof User; // => true

The class syntax is way easier to work if you’re familiar with the classic inheritance mechanism of Java or Swift languages.

Anyways, even if you use class syntax in JavaScript, I recommend you to have a good grasp of prototypal inheritance.

8. Class features availability

The class features presented in this post are spread across ES2015 and proposals at stage 3.

At the end of 2019, the class features are split between:

9. Conclusion

JavaScript classes initialize instances with constructors, define fields and methods. You can attach fields and methods even on the class itself using the static keyword.

Inheritance is achieved using extends keyword: you can easily create a child class from a parent. super keyword is used to access the parent class from a child class.

To take advantage of encapsulation, make the fields and methods private to hide the internal details of your classes. The private fields and methods names must begin with #.

The classes in JavaScript become more and more convenient to use.

What do you think about using # to prefix private properties?_

#javascript #webdev #angular #nodejs #reactjs

Everything you should know about JavaScript Classes