2
var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();

var Greeting = (function(){
    Greeting.prototype = new Greeter();        
    Greeting.prototype.constructor = Greeter;
    function Greeting(greeting){
    } 
    return Greeting;
})();



var greeting = new Greeting("World");
alert(greeting.greet());

I'm trying to manipulate inheritance using javascript prototyping. I have a class structure like above. But when I call the greet method it display some thing like the below image shows. Can anybody guid me on this ?

enter image description here

kapa
  • 77,694
  • 21
  • 158
  • 175
CodeDecode
  • 401
  • 2
  • 10
  • 19
  • This is so complicated it's hard to get you intent. Whatever it is, there's a simpler way to achieve it. – Denys Séguret Jan 27 '14 at 17:36
  • His intent seems to be to inherit the `Greeter` object, and override the constructor – crush Jan 27 '14 at 17:38
  • Seemingly you already have a jsFiddle. You could have posted the link at the same time, so it would be easier for us to play with the code :). – kapa Jan 27 '14 at 17:50
  • Sorry about that next time if I have a question I will be doing it. @dystroy is it a bad way of prototyping in javascript ? It would be a great support if you could explain me further – CodeDecode Jan 27 '14 at 17:56

5 Answers5

2

In your "greet" method of your Greeter you call this.greeting. However, in your Greeting object you haven't defined a "greeting" method...

xspydr
  • 3,030
  • 3
  • 31
  • 49
2

You are never invoking the "constructor" function Greeter when you are creating the Greeting object. So the this.greeting = message; line never runs, that is why it is undefined.

You have to either insert that line manually:

function Greeting(greeting){
    this.greeting = greeting;
}

or invoke the parent constructor:

function Greeting(greeting){
    Greeter.call(this, greeting);
}
kapa
  • 77,694
  • 21
  • 158
  • 175
  • Thank you, and I got the issue any ways I really appreciate your time on this. – CodeDecode Jan 27 '14 at 17:40
  • but I have put a log inside Greeter and it does getting logged in console but with an undefined greeting. – CodeDecode Jan 27 '14 at 17:48
  • @CodeDecode Yes, because of this line: `Greeting.prototype = new Greeter();`. To do your inheritance stuff, you are calling the `Greeter` function, with no parameters - hence the `undefined`. – kapa Jan 27 '14 at 17:49
  • Have one more question is this the proper way of doing inheritance in javascript? I believe I'm not bothering you. Because I got confused with one of the comment posted by @crush – CodeDecode Jan 27 '14 at 17:51
  • @CodeDecode It's hard to tell what is the *proper* way of doing inheritance in Javascript. Some people don't prefer this classical way and there are many different methods. I normally like using an `Object.create()`-based model, not constructors functions and function prototype. – kapa Jan 27 '14 at 17:54
  • 1
    @CodeDecode The second option from above is what you want. I don't know how I confused you. You did the first option above, which is NOT what you wanted to accomplish. – crush Jan 27 '14 at 17:54
  • @crush Thank you, Yeah u put up a valid point. Sorry about my mistake – CodeDecode Jan 27 '14 at 18:06
  • Actually the line *does* run, with `greeting` being `undefined`: `Greeting.prototype = new Greeter();` (just what [one should not do](http://stackoverflow.com/questions/12592913/what-is-the-reason-to-use-the-new-keyword-here)) – Bergi Feb 05 '14 at 00:44
1

When you call greeting.greet(), this.greeting is undefined, thus the problem.

Explanation:

Try this code:

var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();
console.log('Log 1: ' + Greeter);

var Greeting = (function(){
    console.log('Log 2: ' + Greeting);
    Greeting.prototype = new Greeter();        
    console.log('Log 3: ' + Greeting);
    Greeting.prototype.constructor = Greeter;
    console.log('Log 4: ' + Greeting);
    function Greeting(greeting){
    } 
    console.log('Log 5: ' + Greeting);
    return Greeting;
})();

console.log('Log 6: '+Greeting);


var greeting = new Greeting("World");
alert(greeting.greet());

You will see that Greeting is just an empty function, but with Greeter as the prototype. So, new Greeting('World') creates the following function:

function Greeting(greeting){
}

with a prototype containing greeting (undefined), constructor (a function), and greet (a function). Greeting.prototype.greet, in turn, has this definition:

Greeting.prototype.greet = function () {
    return "Hello, " + this.greeting;
};

But this.greeting is undefined in this context, because this refers to Greeting.prototype.greet, not Greeter. Thus, these lines:

var greeting = new Greeting("World");
alert(greeting.greet());

fail, because greeting.greet() returns Hello, concatenated with an undefined value.

elixenide
  • 44,308
  • 16
  • 74
  • 100
1

You call greet method on Greeting context which don't have greeting property.

And there is no reason to wrap code in IIEF in your case, because there is no private vars, so (it works):

var Greeter = function (message) {
    this.greeting = message;
};

Greeter.prototype.greet = function () {
    return "Hello, " + this.greeting;
};

var Greeting = function (greeting){
    Greeter.call(this, greeting)
} 

Greeting.prototype = new Greeter();        

var greeting = new Greeting("World");
alert(greeting.greet());
Alex
  • 11,115
  • 12
  • 51
  • 64
0

change the Greeting class like this:

var Greeting = (function(){
    function Greeting(greeting){
        Greeter.apply(this, arguments);
    }
    Greeting.prototype = new Greeter();        
    Greeting.prototype.constructor = Greeter;
    Greeting.superClass = Greeter;

    return Greeting;
})();

or if you want to create a general solution for all of your inheritance model, do this:

var Greeting = (function(){
    var Greeting = function $SubClass(greeting){
        $SubClass.prototype.constructor.apply(this, arguments);
    }
    Greeting.prototype = new Greeter();        
    Greeting.prototype.constructor = Greeter;

    return Greeting;
})();

The important point in this part:

var Greeting = function $SubClass(greeting){};

is when you directly assign the function to a variable, you would have access to your function based on its label ($SubClass) only in the function context.

Mehran Hatami
  • 12,723
  • 6
  • 28
  • 35