6
\$\begingroup\$

Originally posted this here, and it was helpfully suggested to post in this forum.

In the past couple of years I've returned part time to programming after a 15 year gap. I was C/UNIX. So, I've picked up PHP, Java and C++ ok, but have struggled with JavaScript.

Finally I think I've found a way to 'create' classes that can inherit and wondered if anyone would care to comment. Here is an example:

<!doctype html>
<head>
  <title>Basic</title>
</head>
<body>
  <div id="d1"></div>
  <script type="text/javascript">

function Base( options ) {
    var that = this;
    options = options || {};
    Object.keys( options ).forEach( function( item ) {
        that[item] = options[item];
    });
}

function Creature( options ) {
    this.legs = 4;

    Base.call( this, options );
    console.log("New creature");
}

Creature.prototype.showNumberOfLegs = function() {
    console.log( "Number legs " + this.legs );
};


function Mammal( options ) {
    this.fur = true;
    Creature.call( this, options );

    console.log("New mammal");
}

Mammal.prototype = Object.create( Creature.prototype );

Mammal.prototype.showFur = function() {
    console.log( "Fur " + this.fur );
};

var c = new Creature();
c.showNumberOfLegs();

var m = new Mammal({ legs: 6, fur: false });
m.showNumberOfLegs();
m.showFur();
  </script>
</body>
</html>
\$\endgroup\$
11
\$\begingroup\$

but have struggled with JavaScript

Welcome to JavaScript, where all things look fine but are actually half broken. :D

Finally I think I've found a way to 'create' classes that can inherit

I think there's a saying that goes like "Composition over inheritance". That's because composition is more flexible and doesn't impose hard taxonomies of classes or make you resort to multiple inheritance. See this video for a detailed comparison.

Now let's go over to your code. Let's just say for now that I advocate inheritance. Let's do this!

options = options || {};
Object.keys( options ).forEach( function( item ) {
    that[item] = options[item];
});

// to

Object.keys(options || {}).forEach(function(key){
  this[key] = options[key];
}, this);

// to

Object.assign(this, options || {});

You can streamline your assignment operation by inlining the defaulting of options to an empty object. The context (this) can also be provided to the callback of forEach via its second argument.

If you can do ES6, there's Object.assign() which does the same thing in lesser code. It pretty much looks like jQuery's $.extend if you're familiar with it.


Base.call( this, options );

// to

Base.apply(this, arguments);

The reason is that you don't actually know how many arguments you'll potentially provide the constructor. In your code, you assume your only argument is options, but that might change. apply allows you to pass in an array or array-like object as an argument, spreading it as the arguments on the receiving end.


You are missing:

Creature.prototype = Object.create(Base.prototype);

Here's a checklist of what to do when doing prototypal inheritance manually:

  • Inherit the parent properties (Parent.apply(this, arguments).
  • Inherit the parent prototype (Child.prototype = Object.create(Parent.prototype))
  • Define child properties and their default values
  • Define child methods
\$\endgroup\$
  • 1
    \$\begingroup\$ It's good to remember that Object.keys() is only supported on IE9 and newer. If support for IE8 is required, you need a polyfill or an alternative method. \$\endgroup\$ – Ismael Miguel Oct 5 '15 at 2:21
  • \$\begingroup\$ @IsmaelMiguel The OP did use forEach and Object.create, so maybe it's safe to say the code is for ES5-compatible browsers. \$\endgroup\$ – Joseph Oct 5 '15 at 2:38
  • \$\begingroup\$ Oh, right... Maybe the O.P. may not be aware, since there's nothing saying that IE support isn't a requirement. Now-a-days, I don't even know the amount of bad advices that are around the internet \$\endgroup\$ – Ismael Miguel Oct 5 '15 at 2:41
  • 1
    \$\begingroup\$ where all things look fine but are actually half broken. I'd argue it's the other way around; where all things look broken but are actually just fine. \$\endgroup\$ – Qix Oct 5 '15 at 2:59
  • \$\begingroup\$ Thanks @JosephtheDreamer, that's a great answer - very helpful. And the video - maybe even more helpful :) I'd just got to that problem with my Pet class ... I shall do some thinking \$\endgroup\$ – minisaurus Oct 5 '15 at 6:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.