Solved

Javascript newbie inheritance question

Posted on 2015-02-01
7
77 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
  • 4
  • 3
7 Comments
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
Comment Utility
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
Comment Utility
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 74

Expert Comment

by:käµfm³d 👽
Comment Utility
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:elepil
Comment Utility
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 74

Expert Comment

by:käµfm³d 👽
Comment Utility
...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
Comment Utility
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
Comment Utility
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

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

This article shows how to create and access 2-dimensional arrays in JavaScript.  It includes a tutorial in case you are just trying to "get your head wrapped around" the concept and we'll also look at some useful tips for more advanced programmers. …
Having worked on larger scale sites, we found out that you are bound to look at more scalable solutions to integrating widgets, code snippets or complete applications and mesh them into functional sites, in any given composition. To share some of…
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…

763 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now