Issue
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
Solution
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:
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:
- MDN: Object prototypes
- MDN: Classes in JavaScript
- MDN: Docs for
Function.prototype.call
(to understand the examples) - Jest docs for
spyOn
Answered By - CherryDT
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.