OO style JS - having issues with inheritance

I’ve been trying to learn OO style JS today, but am having an issue with inheritance. I have the following, which seems to work okay, and is hopefully correct:

function Person(name){
    var job; //private
    this.name=name; //public
}
    Person.prototype.setJob=function(jobb){
        job=jobb;
    }
    Person.prototype.getJob=function(){
        return job;
    }
    Person.prototype.getName=function(){
        return this.name;
    }

function Postman(name){
    //construct the parent
    Person.call(this, name);
    //set the job on the parent
    //this.setJob('Postman');
    job="Postman";
}
    //Postman extends Person
    Postman.prototype=new Person();
    Postman.prototype.parent=Person.prototype;
    //Postman constructor will be Person now, so switch it back to Postman
    Postman.prototype.constructor=Postman;

    //Override the parent method
    Postman.prototype.getName=function(){
        //call the parent method to get the name
        return this.getJob()+" "+this.parent.getName.call(this);
    };

var MrsGoggins = new Person('Mrs Goggins');
MrsGoggins.setJob('Shop assistant');
console.log(MrsGoggins.getJob()); //Shop assistant
console.log(MrsGoggins.getName()); //Mrs Goggins

var Pat = new Postman('Pat');
console.log(Pat.getJob()); //Postman
console.log(Pat.getName()); //Postman Pat

The issue is, if I modify the Person object so that name is required e.g.

function Person(name){
    var job; //private
    if(!name){
        throw {"name" : "InvalidArgument", "message" : "name of Person must be supplied", "toString" : function(){return this.name+": "+this.message}};
    }
    this.name=name; //public
}

Then when the script gets to Postman.prototype=new Person(); the error will be thrown as no name is supplied.

So, I’m not sure how you are meant to extend an object if that object requires a parameter to be instantiated?

Yup, this was definitely a problem with JavaScript’s inheritance model. Today, instead of using new Person() to extend the type, you would use Object.create.

Postman.prototype = Object.create(Person.prototype);

The caveat is that IE8 doesn’t support Object.create, so if you still need IE8 support, then you’ll have to monkey patch the global environment a bit.

if (!Object.create) {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

Also, take special care with your “private” variables. That only works if your code follows a specific pattern, where all your methods are defined and attached to each new instance within the constructor itself.

function Person(name){
    var job; //private
    this.name=name; //public

    // define and attach methods to each new instance
    this.setJob=function(jobb){
        job=jobb;
    }
    this.getJob=function(){
        return job;
    }
    this.getName=function(){
        return this.name;
    }
}

Also also, JavaScript very sadly makes it extremely easy to make mistakes. A lot of the places where you referenced what you thought was a job instance variable, you were actually using a global variable. For example:

var MrsGoggins = new Person('Mrs Goggins');
MrsGoggins.setJob('Shop assistant');

var Pat = new Postman('Pat');

console.log(MrsGoggins.getJob()); // Oops. Postman?

We should all consider it a requirement to check our code in JSHint. There are best practices we can adhere to that make JavaScript less error-prone, and JSHint will warn us if we miss one of those best practices anywhere in our code.

Thanks very much for the help and advice Jeff. I’m clearly not understanding the scoping issues, will have to play a bit more and read some more.

Cheers

Dave

@djeyewater;

In contrast to some other programming languages, it is perfectly legal in JavaScript to omit parameters even if the function has been defined to accept these arguments. The missing parameters are simply given the value undefined.

So you got it all wrong. throw mechanism is what’s getting in the way, no matter what, since it’s "natural habitat’ is inside a try…catch. Also, throwing string values, is rarely a good idea, because it makes it hard to recognize the type of the exception.

Example 1


function Person(){
    var name = arguments[0];
    if(!name){
        throw {"name" : "InvalidArgument", "message" : "name of Person must be supplied", "toString" : function(){return this.name+": "+this.message}};
    }
    this.name=name; //public
}

try {
    var somebody = Person();
    console.log(somebody);
} catch(e) {
    console.log("Why would you leave me nameless?!");
}

Example 2


function Person(){
    var name = arguments[0];
    if(!name){
        throw {"name" : "InvalidArgument", "message" : "name of Person must be supplied", "toString" : function(){return this.name+": "+this.message}};
    }
    this.name=name; //public
}

Person.prototype.setJob=function(jobb){
    job=jobb;
}
Person.prototype.getJob=function(){
    return job;
}
Person.prototype.getName=function(){
    return this.name;
}

function Postman(name){
    //construct the parent
    Person.call(this, name);
    //set the job on the parent
    //this.setJob('Postman');
    job="Postman";
}

try {
    //Postman extends Person
    Postman.prototype=new Person();
    Postman.prototype.parent=Person.prototype;
    //Postman constructor will be Person now, so switch it back to Postman
    Postman.prototype.constructor=Postman;
    
    //Override the parent method
    Postman.prototype.getName=function(){
        //call the parent method to get the name
        return this.getJob()+" "+this.parent.getName.call(this);
    };

var MrsGoggins = new Person('Mrs Goggins');
MrsGoggins.setJob('Shop assistant');
console.log(MrsGoggins.getJob()); //Shop assistant
console.log(MrsGoggins.getName()); //Mrs Goggins

var Pat = new Postman('Pat');
console.log(Pat.getJob()); //Postman
console.log(Pat.getName()); //Postman Pat
} catch(e) {
    console.log("My way or the highway");
}

Also, you got it wrong when you try to define constrains in the “class” constructor (object constructor really, you should drop any nostalgia from other languages and embrace the prototypal inheritance and terminology; while you’re at it, renounce exception handling also, you know, throw, try…catch and such, there are better ways, better to learn how to catch Javascript ball). Instead, you simply put that constrain when creating new objects instead:


if (name) {
  var name = new Person(name);
}

I think the community refers to this as one-stage vs two-stage construction. The OP is certainly welcome to try both approaches, but I don’t think there’s a consensus about which is the better approach. Personally, I can’t think of a good reason why a JavaScript constructor shouldn’t throw exceptions.

http://stackoverflow.com/a/77705/1698612

while you’re at it, renounce exception handling also, you know, throw, try…catch and such

Same deal. Could be worth exploring, but “renounce exception handling” is by no means standard practice in JavaScript.

Well, if an exception is thrown with object creation, and proper exception handling is in place (one important missing part which the OP doesn’t have), normally the only code to be executed is an object deconstructor. This is the part where I mentioned the OP should embrace Javascript. Javascript is not C, so we don’t do fine grain memory allocation control with it, we code smart, we don’t get in the GC way and let GC do its work.

Same deal. Could be worth exploring, but “renounce exception handling” is by no means standard practice in JavaScript.

There is a use case for error handling by throw in Javascript, but it must be treated like an… exception! It must be something… exceptional! Otherwise, normal error handling is the norm: check for an error before doing the work or check and resolve on spot for error the returning result.

The problem is not only with Javascript, but with “after the fact” error handling. Like I said, a throw must have a corresponding try…catch. But this means that an error will most likely occur only after some constructor and/or some other work has already began in this case.

The main problem is understanding when to throw errors. And remember, the mission for the corresponding try…catch with objects is two step: first to deconstruct and then to handle errors in the most specific way possible, certainly not in a general manner.

Doing it the clean way, like I did, keeping constraints outside the constructor, assures error handling on spot, before the fact, before entering or calling the constructor, before any work is done: if criteria is met then enter the constructor.

Doing it like the OP did, putting the constrains inside the constructor results in a messy way of error handling, after some work has already been done: first entering or calling the constructor, then checking if criteria is met: throwing the error and then handling the error. The first two steps are memory consuming for nothing (why would you want to load the constructor before checking if you meet the criteria) and the last step is bound to make you forget to catch one thing or another.

Erm… I’m not sure why destructors and C became part of this conversation.

This is JavaScript. There is no “deconstruct” step. Are you perhaps coming from a C++ mindset?. Certainly in languages like C++, exception handling gets more tricky because you also have to free allocated memory.

The downside is that there’s no assurance of correctness. If the programmer has to do some error checking each and every time before invoking a constructor or any function for that matter, then eventually there will be a place in the code where the programmer forgot, or where the programmer didn’t cover all the cases he was supposed to check for. If, on the other hand, the constructor checked its own arguments and threw an error as appropriate, then it would be pretty much impossible to construct an object and not perform these checks.

This kind of error handling gets extremely tedious for the programmer, to have to check the return value after every call to any function at every level of the call stack that might encounter an error. Plus it’s harder to convey exactly what kind of error was encountered. Plus the function’s valid return values might leave few choices for an “error” return value.

var result = doSomething();
if (result === null) {
    // does null mean "no value" or does it mean "error"?
    // if it's an error, then why exactly did it fail?
    // if this is an error that can't or shouldn't be handled at this level
    // then all I can do is pass the error further up the call stack
    return null;
}

By contrast, when exceptions are used, programmers don’t have to explicitly check every return value. They can try/catch a whole block of code at once. Or they can allow the exception to cascade up the call stack where certain kinds of errors are more properly handled. Plus exceptions can specify exactly what kind of error occurred with a detailed message. Plus there is zero overlap between valid return values and errors.

Worrying about the memory consumption of entering a function before throwing an error sounds like a micro-optimization to me. And although, yes, the programmer might forget to catch an exception, the worse alternative is that the programmer might forget to check for an error condition entirely.

Though I do want to add that this is not a clear-cut issue. Some very smart people have tried and continue to try going exceptionless. Google’s C++ style guide reads like a back-and-forth debate. They start off saying they don’t use exceptions. Then they give a nice pro/con list. Then they say, “Things would probably be different if we had to do it all over again from scratch.” And that, “On their face, the benefits of using exceptions outweigh the costs, especially in new projects.”

On the other hand, Google’s Go programming language was designed to be exceptionless.

On the other other hand, Google’s JavaScript style guide says yes, use exceptions.

It’s certainly an interesting idea that’s worth exploring, but for people who are still learning, like the OP, I think we should avoid saying that there is a definite right or wrong choice (because there isn’t), and I think we should avoid saying that exceptionless is standard practice in JavaScript (because it isn’t).

I said exceptions have their place in Javascript, just not in the constructor.

For an example where I would use exceptions, see this thread: http://www.sitepoint.com/forums/showthread.php?1164061-Python-have-more-power-than-php&p=5577834&viewfull=1#post5577834

And why, exactly? (When you tried to explain this before, you ended up talking about destructors and C.)

I have explained it before, you just didn’t try to understand.

Because that’s the pattern in other languages for using exceptions with object constructors: if an exception occurs, the only thing to do is to free the memory up from whatever leftover the constructor started generating.

In Javascript this doesn’t apply, you don’t usually clean up memory, even if it can be done. You let the GC work.

And it’s also simpler, smarter, cleaner to just check for new object criteria before calling the constructor.

Weren’t you saying earlier that JavaScript is not C, and we should embrace JavaScript? It doesn’t matter what other languages do.

Thank you. That’s kinda my point. In C++, there may be a good reason to avoid exceptions in the constructor, but in JavaScript, it’s not a problem.

What can I say. You got it backwards. You misconstrue. Have it your way.

@Jeff_Mott;

Maybe this is doing a better job to convince you throwing errors should be used sparsely in Javascript, and support my claim about well known issues when throwing errors: http://flippinawesome.org/2013/09/30/rethinking-javascripts-trycatch/

It is such a powerful construct that in a perfect world you would want to wrap everything in a try/catch block to provide simple and effective error trapping. However, due to concerns in performance critical situations, employing it is often frowned upon in JavaScript.

[…]

No matter what context you use a try/catch block in, there will always be an inherent performance hit, quite possibly a substantial one.

I’d expect if you choose to carry on antagonistically to at least post some legitimate sources as well.

Before you get too snarky, you should at least realize that the article you linked to makes a completely different argument with completely different reasoning than what you were saying. Your arguments were “renounce exception handling,” and “you got it wrong when you try to define constrains in the ‘class’ constructor.”

In contrast, the article you linked to doesn’t say anything about when you should or shouldn’t throw. It’s whole premise is to offer a custom try/catch construct that’s supposed to deliver better performance. It still expects you to throw exceptions in the normal way.

EDIT: And to boot, their’s is a micro-optimization. They say “90% loss in performance,” but they don’t say what that actual time is. Turns out that 90% is equal to four nanoseconds (that is, four one-thousandths of a microsecond).

Man, are you that thick? What did you expect the article to say: “Yes Jeff, myty is right!”? And yes, they’re making the same argument: use error throwing sparsely. It’s an art, error throwing, and so beginners should just stay off it. If “employing it is often frowned upon in JavaScript” doesn’t convince you, what does?

Just please stop with the act and please link back with something substantial and legitimate! Link to at least a quasiknown piece of software that uses throws in the constructors or error throwing extensively. OK?

Here it is, one more: http://stackoverflow.com/questions/3217294/javascript-try-catch-performance-vs-error-checking-code

Avoid try-catch in performance-critical functions, and loops
[…]
Use them wisely, use them sparingly.
[…]
But as I see you clearly misuse some functions for error checking. You can test for the desired objects and properties of objects right before you use them instead of complex checking.

And before you again say they’re saying something different:

Here’s another: http://developer.nokia.com/Community/Wiki/JavaScript_Performance_Best_Practices

Or if possible, avoid try-catch-finally completely

Here’s another: http://programmers.stackexchange.com/questions/144326/try-catch-in-javascript-isnt-it-a-good-practice

One should avoid throw errors as the way to pass error conditions around in applications.
The throw statement should only be used “For this should never happen, crash and burn. Do not recover elegantly in any way”
try catch however is used in situation where host objects or ECMAScript may throw errors.
[…]
There are also other issues like try / catch is really expensive and it’s ugly and it simply doesn’t work with asynchronous operations.

So since synchronous operations should not throw an error and it doesn’t work with asynchronous operations, no-one uses try catch except for errors thrown by host objects or ECMAScript

and in comments:

I wouldn’t go so far as to say no one uses try catch, it’s just the wrong tool for the job in most cases. When there are truly exceptional circumstances, it can be worthwhile to throw an Error, but they are few and far between.

and yes, they’re agreeing with me:

Now, please get a little snarky in return and post something better. I am in favor of changing my programming habits even if it’s a 180, but let it be something serious.

I expected it to back up the points you were trying to make. It didn’t.

See, the thing is, this claim is extremely easy for anyone to check. The article you linked to definitely said no such thing. The word “throw” is only even used just once. Here’s the sentence: “The event is capable of detecting runtime errors including any errors that you explicitly throw yourself.” It says absolutely nothing about when you should or shouldn’t throw.

Such as, perhaps, Google style guides? Look above. I already did that. Or if you like StackOverflow, then look above, I linked to a SO answer as well.

Couple things here. 1) The answer is talking about the performance of try/catch. Not about throwing in a constructor, or even about throwing in general. And 2) Look at the SO answer I linked to above. Which, by the way, is exactly on topic. It’s about whether it’s OK to throw from a constructor. The top voted answer says, “I’ve never understood the reasoning behind this approach. I’m firmly in the group that supports one-stage construction.”

And just to reiterate, I never said that it’s absolutely right to throw from the constructor. You told the OP that he was absolutely wrong, and my rebut was, “I don’t think there’s a consensus about which is the better approach.” That seems to me to be a calm and reasonable and accurate rebut. So… chill.

This says the same thing as all your other links: “Don’t use try-catch-finally inside performance-critical functions.” And if your argument was to avoid exceptions in performance critical places, then I would certainly agree with you. But that wasn’t your argument, nor is it what I’ve been rebutting all this time. Your argument was about whether it’s OK to throw from a constructor, and whether we should “renounce exception handling” in general, regardless if it’s performance critical or not. None of your links have backed up that argument.

Finally, for the first time, a link that supports (part) of your argument. So what we have now is a SO answer that says one thing, and a SE answer that says another. Pretty sure this backs up my statement that there’s no consensus. If we can agree on at least that much, then we can start a new thread and discuss the pros and cons of exception handling, and hopefully we’ll both come out of it knowing something that we didn’t before.