Solved

Javascript newbie inheritance question

Posted on 2015-02-01
7
97 Views
Last Modified: 2015-02-02
I'm doing a very simple test on inheritance with JavaScript, and it doesn't seem to be working.

I have a Person object type with just one property called 'name', and one method, called sayName().

I want to create a subtype called Woman which inherits the sayName() function from the Person object. When the Woman object is trying to invoke the sayName() method, I am getting an error message, and I don't know why.

Can someone look at my brief code snippet and tell me what I'm doing wrong, please?

function Person(name) {
                this.name = name;
                this.sayName = function() {
                    console.log(this.name);
                };
            }

            function Woman(name) {
                this.name = name;
            }

            Woman.prototype = Object.create(Person.prototype, { // Trying to do Inheritance
               constructor : {
                   enumerable: true,
                   configurable: true,
                   writable: true,
                   value: Woman
               } 
            });

            var woman = new Woman("Jane");

           /* I'm getting an error on the next line: "Uncaught TypeError: undefined is not a function". What I'm doing wrong? */
            woman.sayName();

Open in new window

0
Comment
Question by:elepil
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 40583293
You need to add the sayName method to Person's prototype:

function Person (name) {
    var self = this;
    
    self.name = name;
}

Person.prototype.sayName = function () {
    console.log(this.name);
};

...

Open in new window


Then it should work. You can see examples of such here:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
0
 

Author Comment

by:elepil
ID: 40583302
kaufmed, thanks for responding. Then can you explain to me why this works? It's almost identical to the my code snippet, simpler actually, and it works without my having to assign sayName() to the prototype:

            function Person(name) {
                this.name = name;
                this.sayName = function() {
                    console.log(this.name);
                };
            }

            function Woman(name) {
                this.name = name;
            }

              Woman.prototype = new Person();
              Woman.constructor = Woman;

            var woman = new Woman("Jane");
            woman.sayName();

Open in new window

0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 40583327
Oooooh...  I was afraid you'd ask me that. I'll try my best to explain, but I've just been reading up on this topic myself. I come from a C# background, so this prototypal inheritance is pretty odd to me. Feel free to await further resposnes.

From what I read, it basically comes down to how you set up the inheritance. With my approach, I continued with your use of Object.create. That function creates a new object, and the object that is created has its prototype point to the object that was passed in to the function. In your original code, that means that the prototype of Woman is a new object whose parent prototype is that of Person. Graphically:

null<=Object.prototype<=Person.prototype<=Woman.prototype

When you assign to the prototype, you are basically saying that all instances of a "class" will have that method, and that method will exist only once in memory. When you do not assign to the prototype, each instance of the "class" will have that method, but each instance will have a distinct instance of that method as well. This means you have multiple copies of the method in memory...for no decent reason.

The reason your new code works is because you set Woman's prototype equal to a new instance of the Person "class", and that "class" has its own instance of the sayName method. This may be fine...I'm not 100% sure. But I do know that you've basically got it set up such that any new instance of a Woman points to one instance of Person, because you only created that one and assigned it directly to prototype of Woman. I don't know enough to tell you whether or not this is a good practice.
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 

Author Comment

by:elepil
ID: 40583331
kaufmed, correct me if I'm wrong. By making Woman a "subclass" or subtype of Person, if I try to access "sayName" in Woman, it will look at its OWN properties, and it won't find it. It will then look at Woman's prototype and will not find it there. My understanding is that JavaScript would then ascend up the prototypal chain, correct? That means, JavaScript should look next at Person's own properties, and it should find the sayName there. Do we have the same understanding on this?

Because if we do, that was my explanation to myself why the second example works. In fact, I thought it should've worked with BOTH examples, and it has been driving me nuts since this morning why it would not work for the first method.

Is there anything wrong with the way I am understanding this, in your opinion?
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 40583338
...it will look at its OWN properties, and it won't find it. It will then look at Woman's prototype and will not find it there. My understanding is that JavaScript would then ascend up the prototypal chain, correct?
That is what I had read, yes. I *think* the issue with your first is that the method as declared isn't a part of the prototype, though. That is what my example is doing:  adding the method to the prototype.
0
 

Author Comment

by:elepil
ID: 40583355
To be honest, I was aware that adding the function to the prototype would make it work because my book clearly states that a prototype is shared across ALL instances of that type. In fact, my book explicitly says the above two examples should've behaved identically, except the first example had the added benefit of not having to worry about the Person constructor requiring its parameter. I was so surprised when the first example didn't work.

Anyway, thanks for responding. What I really needed was an explanation why the first method did not work, and how to make it work. The second method is risky because if the Person constructor had code that throws an error if the parameter it's expecting is absent, it will be a problem. For that reason, I'd rather never have to use the second method if I can help it.
0
 

Author Closing Comment

by:elepil
ID: 40584331
kaufmed, I saw this article: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript. It was using Person as the supertype and Student as the subtype, and it says:

// Create a Student.prototype object that inherits from Person.prototype.
// Note: A common error here is to use "new Person()" to create the
// Student.prototype. That's incorrect for several reasons, not least
// that we don't have anything to give Person for the "firstName"
// argument. The correct place to call Person is above, where we call
// it from Student.

I'm not going to bother seeking an explanation why the second method works, as Mozilla itself flags it as wrong. I'm just going to stick to doing it this way:

        /* Person is the supertype */
        function Person(name) {
            this.name = name;
        }
        /* Define all methods and properties you want to allow subtypes to 
         * access in the prototype. */
        Person.prototype.sayName = function() {
            console.log("I say my name is " + this.name);
        };
        
        /* Man is a subtype of Person */
        function Man(name) {
            /* This is the 'super' counterpart in JavaScript */
            Person.call(this, name);
        }
        /* This is what makes inheritance work. This links Man to Person as a 
         * subtype */
        Man.prototype = Object.create(Person.prototype);
        Man.constructor = Man;
        /* Man object also has a method it wants to allow subtypes to inherit */
        Man.prototype.roar = function() {
            console.log(this.name + " roars!");
        }
        
        /* Boy is a subtype of Man */
        function Boy(name) {
            this.name = name;
            this.pat = function(name) {
                console.log(this.name + " is patting " + name);
            };
        }
        Boy.prototype = Man.prototype;
        Boy.constructor = Boy;
        
        var person1 = new Person("Dad");
        var man = new Man("David");
        var boy = new Boy("PeeWee");
        
        boy.sayName(); // Inherited from Person
        boy.roar(); // Inherited from Man
        boy.pat("Dad"); // boy's own OWN method

Open in new window


Thanks for responding!
0

Featured Post

PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
modify change color of text 9 50
Set css in function 11 54
Google Chrome: Debugging AJAX call 6 38
Convert complicated date to yyyy-mm-dd format 22 50
In Part 1 (http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/A_7849-Hex-Maze.html) we covered the hexagonal maze basics -- how the cells are represented in a JavaScript array and how the maze is displayed.  In this part, we'…
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question