What is the difference between an object and an object from a class in JavaScript?

Viewed 2396

I'm learning JavaScript and Java at work and in school. As far as I know, in Java, you always have a class and from that class you can create objects. Same works in JavaScript, BUT: In JavaScript it's possible to create objects without classes.

So my question is: what is the difference between those two kinds of objects in JavaScript?

class Test {
    say() {
        console.log("I'm a test.");
    }
}

let TestFromClass = new Test();

let TestFromObject = {
    say() {
        console.log("I'm also a test.");
    }
};


TestFromClass.say();    // Output: I'm a test.
TestFromObject.say();   // Output: I'm also a test.

Now I wanted to know if there is a difference in them, or if we actually need classes in JavaScript.

5 Answers

When you use new, you construct a new object whose internal prototype is the class's prototype. For example:

class Test {
    say() {
        console.log("I'm a test.");
    }
}

let TestFromClass = new Test();
console.log(Object.getPrototypeOf(TestFromClass) === Test.prototype);

This is useful when you need to create multiple objects. Usually, such objects are created because they'll have some sort of state associated with each individual object, usually in the form of properties on the object (eg, a person object might have a name and an age property).

But if you don't have any data associated with an instance (in your example, the TestFromClass object), there's not much point having an instance at all.

If you only want to collect named functions into a data structure, your TestFromObject makes much more sense than a class.

That said, you may want to have a class that has some functions associated with it (like say) which don't have anything to do with an instance of its data, while still being able to create an instance, perhaps with other methods on the prototype. This isn't that uncommon, and is done by making the non-instance-related functions static:

class Person {
  static canEat() {
    return ['apples', 'bananas', 'carrots'];
  }
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
const p = new Person('Bob', 99);
console.log(p.name);
console.log(Person.canEat());

What is the difference between an object and an object from a class in JavaScript?

There effectively aren't any in the general sense. Some things that may seem a bit like differences, though:

  • When you create an object with literal syntax, unless you use the special __proto__ property (officially browsers only), its prototype will always be Object.prototype. When you create it with new X, provided X is a constructor function created with class syntax, the result will have the prototype X.prototype.
  • Methods defined within an object literal are directly placed on the object. Methods within class X go on X.prototype (non-static ones) which the object inherits.

Objects come in two forms: the declarative (literal) form, and the constructed form.

The literal syntax for an object looks like this:

var myObj = {
    key: value
    // ...
};

The constructed form looks like this:

var myObj = new Object();
myObj.key = value;

The constructed form and the literal form result in exactly the same sort of object. The only difference really is that you can add one or more key/value pairs to the literal declaration, whereas with constructed-form objects, you must add the properties one-by-one.

Note: It's extremely uncommon to use the "constructed form" for creating objects as just shown. You would pretty much always want to use the literal syntax form. The same will be true of most of the built-in objects.

P.S. To read more in detail go to https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/this-object-prototypes/ch3.md

First of all, a class is (almost) just syntactic sugar for a prototype:

// The class way
class Test {
  say() {
    console.log("I'm a test.");
  }
}


// The old fashioned way
function Test() {

}

Test.prototype.say = function () {
  console.log("I'm a test.");
};

The difference in both these cases with direct object creation is that the methods belong to the prototype, not directly to the object.

When you use TestFromClass.say() it goes through the prototype chain to find a say method while TestFromObject directly has the method.

Other than that, there's no difference.

So you created a class called Test which is the base class. The you added a method called say() {}.

class Test {
    say() {
        console.log("I'm a test.");
    }
}

Then you created an instance of the Test class below:

let TestFromClass = new Test();

And below that you created a plain JavaScript object called TestFromObject:

let TestFromObject = {
    say() {
        console.log("I'm also a test.");
    }
};

And yes, they will both print out the output you have to their methods:

TestFromClass.say();    // Output: I'm a test.
TestFromObject.say();   // Output: I'm also a test.

The difference will not begin until you utilize the full power of the class you created, for example, utilizing the cconstructor() function like so:

class Test {
    constructor() {

    }
    say() {
        console.log("I'm a test.");
    }
}

Now the constructor function is automatically called for us when we use the new keyword for the class name. With a constructor function you know also have access to this like so:

class Test {
    constructor() {
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

Which allows you to do this:

TestFromClass.say();    // Output: I'm a test.
TestFromObject.say();   // Output: I'm also a test.
TestFromClass.type;     // Output: test

The constructor is traditionally used to do some initial setup inside the class or particular instance of the class.

The constructor is commonly used by using some arguments when creating a new instance of the class. Maybe you want to specify that the class of Test you have created has 50 questions. You can pass in an object to the new Test instance like so:

let TestFromClass = new Test({ questions: 50 });

You can call this object whatever you want, let's just call the object examination and you can set the number of questions to this examination object.

So now you pass that object into the constructor function and calling that object, examination like so:

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

let TestFromClass = new Test({ questions: 50 });

TestFromClass.say();    // Output: I'm a test.
TestFromClass.type;     // Output: test
TestFromClass.questions; // 50

The other thing you can do with a class object is create a subclass that would extend the functionality of your base class and then you can also add some customized functionality to it.

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

class Quiz extends Test {

}

So now your Quiz is inheriting all the methods, functions, properties, etcetera that are in the Test class and define additional methods inside of it.

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

class Quiz extends Test {
    constructor(examination) {
    this.topic = examination.topic;
  }
}

So now to ensure that the constructor function from the parent class is called as well, I can use the super() keyword into the constructor:

class Test {
    constructor(examination) {
      this.questions = examination.questions;
      this.type = 'test';
    }
    say() {
        console.log("I'm a test.");
    }
}

class Quiz extends Test {
    constructor(examination) {
    super(examination)
    this.topic = examination.topic;
  }
}

Then you can instantiate that subclass like so:

const javascript = new Quiz({topic: 'javascript', questions: 50 });

and finally print it out:

javascript.questions; // Output: 50
Related