Reputation: 77
I have decided to exercise in js and code call function. Nevertheless, I got stuck with "undefined undefined"
output.
Here is the code:
var alex = {
name: "alex",
surname: "surname",
}
let nameyourself = function() {
console.log(`${this.name} ${this.surname}`);
}
Function.prototype.calling = function(smth) {
smth.__proto__.calledfunct = this;
return smth.__proto__.calledfunct();
}
nameyourself.calling(alex);
But when I delete .__proto__
, everything works fine. I suppose that the function doesn't get the context of alex
.
Upvotes: 0
Views: 61
Reputation: 77
That is how I fixed it:
var alex={
name:"alex",
surname:"surname",
}
let nameyourself = function(){
console.log(`${this.name} ${this.surname}`);
}
Function.prototype.calling=function(smth){
console.log(Object.getPrototypeOf(smth));
smth.__proto__.calledfunct=this;
return smth.calledfunct();
}
nameyourself.calling(alex);
Upvotes: 0
Reputation: 18619
You're right, that's because it doesn't get the right context.
Let's inspect:
When you do this:
nameyourself.calling(alex)
...smth
gets the value of alex
, i.e. {name:"alex", surname:"surname",}
.
smth
's [[Prototype]]
(the internal property represented by __proto__
) is Object.prototype
, as smth
is a plain object.
So this line:
smth.__proto__.calledfunct=this
...is essentially equal to:
Object.prototype.calledfunct=this
Then, you call it like this (for the same reason as above):
Object.prototype.calledfunct()
Since the context will be the object whose property is called in case of a method call, nameyourself
is called with the context Object.prototype
.
You get undefined
twice because Object.prototype
has neither name
nor surname
properties.
Test it yourself:
var alex = {
name: "alex",
surname: "surname",
}
let nameyourself = function() {
console.log('Object.prototype === this',Object.prototype === this) //true
console.log(`${this.name} ${this.surname}`);
}
Function.prototype.calling = function(smth) {
console.log('smth', smth)
console.log('smth.__proto__', smth.__proto__)
console.log('smth.__proto__ === Object.prototype', smth.__proto__ === Object.prototype) //true
smth.__proto__.calledfunct = this;
console.log('smth.__proto__.calledfunct', smth.__proto__.calledfunct)
console.log('Object.prototype.calledfunct', Object.prototype.calledfunct)
console.log('smth.__proto__.calledfunct === Object.prototype.calledfunct', smth.__proto__.calledfunct === Object.prototype.calledfunct) //true
return smth.__proto__.calledfunct();
}
nameyourself.calling(alex);
Side notes on this solution:
Although this code works (without .__proto__
s at least), contains multiple bad practices. It's OK for testing, but the use of this code in production is a bad idea.
Problems:
enumerable
: define them with Object.defineProperty
insteadFunction#call
or Function#apply
methods insteadUpvotes: 2