Home > OS >  What is class.prototype and what is the merit of use it
What is class.prototype and what is the merit of use it

Time:09-02

I've found folloing sample in which As if Service class has prototype property.

①Service is not instansiated, why Service = new Service() didn't need ?

console.log(Service.prototype returned {},what is this object ? What is the merit to manipulate this?

beforeEach(async ()=>{
    jest.spyOn(Service.prototype, 'execute')
})

I am totally novice to this concept, if someone has opinion will you please let me know. Thanks

CodePudding user response:

What this does is that whenever .execute(...) is called on any Service instance, your spying thingy would fire.

It doesn't need new Service() because it's not working on a single service instance, it is working on the class itself.

It works by replacing Service.prototype.execute with a wrapper function that logs the call and then calls the original function, something like this:

const oldExecute = Service.prototype.execute
Service.prototype.execute = function (...args) {
  console.log('execute called!', args)
  return oldExecute.call(this, ...args)
}

Class methods are nothing other than properties on the class' prototype, so if you have class Test { hello (x) { return x * 2 } } and you do console.log(Test.prototype.hello), it will log the method hello (x) { return x * 2 }, and if you do testInstance.hello(123) it essentially then calls Test.prototype.hello.call(testInstance, 123), i.e. it calls the function Test.prototype.hello with testInstance as this.

And the {} that you see is not everything there is, because the methods are by default non-enumerable. You should look at it in a debugger that also shows non-enumerable properties. Then you will see the class' methods there:

enter image description here

This is also the reason why when referring to the "full name" of a class method, often ClassName.prototype.methodName is used, because that's actually how you would get that method itself without referring to a particular class instance (to make use of it, you would have to call it with its this set to some instance, though, like what I did with .call above). For example, the slice function that exists on Array (when you write [1, 2, 3].slice(1) for instance) is referred to as Array.prototype.slice (in other languages this would be called Array::slice, Array#slice or the like). Sometimes you will also see people talking about Array.slice but that's technically not correct because slice is not a static method and doesn't exists on Array itself (unlike, for example, Array.from).


Further reading:

  • Related