Reputation: 4618
So i have this constructor function and some prototype methods:
var test = function(name, surname){
this.name = name
this.surname = surname
}
test.prototype.hello = function(){
console.log("hello " + this.name)
}
test.prototype.hi = function(name){
console.log("hi " + this.name)
}
test.prototype.hi.surname = function(){
console.log("hi " + this.surname + this.name)
}
And i call it like this:
var hii = function(){
var x = new test("kevin", "vanhove")
x.hello()
x.hi.surname()
}()
Why is it that the call to x.hi.surname() is giving me this output (function body)?
hello kevin
hi function (){
console.log("hi " + this.surname + this.name)
}
Upvotes: 0
Views: 24
Reputation: 25895
As Pointy already did a good job answering the core question, I'll just add that sometimes the easiest way to deal with this
is to not deal with it at all.
function createTest(name, surname){
var test = { name: name, surname: surname };
test.hello = function(){
console.log( "hello " + test.name );
}
test.hi = function(){
console.log( "hi " + test.name );
}
test.hi.surname = function(){
console.log( "hi " + test.surname + ' ' + test.name );
}
return test;
}
var hii = function(){
var x = createTest("kevin", "vanhove");
x.hello();
x.hi.surname();
}()
Here's the takeaway from the article linked above:
I worked on a team which built a quite large JavaScript application this way. We ended up using this maybe 10 times in the entire multi-thousand-line codebase, and we were quite happy about it.
Why did we find this approach successful? Firstly, it allowed us to sidestep the subtle gotchas involved with the way this works in JavaScript. No more confusion over jQuery re-binding this to the thing being iterated over, for example. Secondly, the ability to compose our own types on an ad hoc basis inside constructor functions turned out to be very powerful. It gives you the useful parts of multiple inheritance, but without the related diamond dependency issues. Finally, the biggest win was the fine-grained control of the API of each type, with all non-public functionality safely hidden from view inside the constructor function’s closure. I believe this was a significant reason for our success in working as a team on a large codebase.
Upvotes: 1
Reputation: 414036
When you call
x.hi.surname();
the value of this
inside the "surname" function will be a reference to the function "hi". It's the last .
that counts. This, this.surname
refers to the "surname" property of the "hi" function, which is of course the "surname" function itself.
I can't think of a good way to set up a structure like the one you seem to want. There's only one "hi" function, on your prototype. I suppose you could create a distinct "hi" property for each constructed object, and a bound "surname" function too:
var test = function(name, surname){
function hi(name) {
console.log("hi " + this.name)
}
function surname(){
console.log("hi " + this.surname + this.name)
}
this.name = name;
this.surname = surname;
this.hi = hi;
this.hi.surname = surname.bind(this);
}
Upvotes: 1