kevinius
kevinius

Reputation: 4618

JS: prototypal inheritance child method gives me the function body

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

Answers (2)

JDB
JDB

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();

}()

http://jsfiddle.net/x4gdzahp/

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

Pointy
Pointy

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

Related Questions