Reputation: 25996
I am trying to learn JS/ES and am a bit confused about classes and objects.
The two code snippets below do exactly the same, but the last one is clearly using a class. But what is the first using? I thought a class became an object when executed?
I would have expected clock
to be a function, but it can apparently be used as an object. Why is that?
And why would anyone ever want to use the class way, when the first is shorter to type?
var clock = {
start() {
setInterval(() => console.log(Date()), 1000)
}
}
clock.start()
and
class Clock {
start() {
setInterval(() => console.log(Date()), 1000)
}
}
const c = new Clock
c.start()
Upvotes: 1
Views: 131
Reputation: 3230
Classes are templates for objects. They describe how a bunch of objects behave. In javascript, new Clock()
is how you get a new object of the class Clock
.
The object literal syntax ({foo: 'bar'}
) is a shortcut to create a generic object. So the class of an object created that way is Object
. Also, creating an object that way doesn't give you a way to make new
objects with the same behavior (which would mean in a sense they would be of the same class).
In some languages like C++ and Java, classes are fundamental building blocks of the language. But in javascript, it's just a concept, and basically means (informally) any object that has the same specified behavior. More formally though it is an object that has the class prototype in its prototype chain. What are prototypes and prototype chains? Well, every* object (even those made with the object literal syntax) has a prototype as a hidden** property. When looking up a property in the object, if it isn't found in the object itself, it looks up the property in the prototype. And if that prototype object doesn't have that property, it goes "up the chain" and checks the prototype's prototype for the property, and keeps doing that as far as it can.
When you use the class
syntax, you are setting properties on the prototype for every object that class creates. So in your example, you are assigning the function start
to the prototype for every Clock
object. But if you assign it to the object itself, then it doesn't use a prototype.
Interestingly, classes are also objects (they can have properties and methods).
For official documentation, see here:
*: You can make an object without a prototype using Object.create(null)
, but those are rare. The benefit of this is that you can't accidentally access properties of the prototype, because there are none.
**: You can sometimes access the prototype using the deprecated __poto__
property. The preferred new way is Object.getPrototypeOf(object)
Here are some examples you can explore:
const clockByLiteral = { start(){/* do something */} }
function startClock () { /* do something */}
class Clock {
start() { /* do something */}
}
const clock1 = new Clock()
const clock2 = new Clock()
function getClassName(object){
return object.constructor.name
}
console.log('"class" of clockByLiteral:', getClassName(clockByLiteral))
console.log('"class" of clockByLiteral.start:', getClassName(clockByLiteral.start))
console.log('"class" of startClock:', getClassName(startClock))
console.log('"class" of Clock class:', getClassName(Clock))
console.log('"class" of clock1:', getClassName(clock1))
console.log('"class" of clock2:', getClassName(clock2))
console.log('is the constructor of clock1 Clock?:', clock1.constructor === Clock, "(meaning that classes and constructors are the same objects, and are functions also")
console.log('is the prototype of clock1 Clock.prototype?:', Object.getPrototypeOf(clock1) === Clock.prototype)
console.log('is clock1 the same object as clock2?:', clock1 === clock2)
console.log('is clock1.start the same as clock2.start?:', clock1.start === clock2.start)
console.log('is clock1.start the same as Clock.prototype.start?:', clock1.start === Clock.prototype.start)
console.log('is clock1 an "instance" of Clock?:', clock1 instanceof Clock)
console.log('is clock1 an "instance" of Object?:', clock1 instanceof Object)
console.log('is clock1 an "instance" of Function?:', clock1 instanceof Function)
console.log('is Clock an "instance" of Function?:', Clock instanceof Function)
console.log('is startClock an "instance" of Function?:', Clock instanceof Function)
console.log('is startClock an "instance" of Object?:', Clock instanceof Object)
Upvotes: 3