1

I have a few problem with JavaScript inheritance and prototype. All the research I have made, in stackoverflow/google lead me to use the prototype of my class, but that's the point I want to avoid. I know JavaScript is not conceived that way but I'm sure it's possible, I'm just stuck.

I have two classes (or more maybe later). One is the base, that will be the mother of all, I want it to have all the basics attributes and method (like a basic OO). My objects are for geometry.


    function EnvObject(){
      this.position = {x: 0, y: 0};
      this.velocity = {x: 0, y: 0};
      this.mass = 0; // kg
      this.restitution = 0; // Restitution
      this.A = 0;
      this.Cd = 0; // Drag force
    
      function init(_x, _y, _mass, _restitution)
      {
        blabla
      };
    };
    
    function oCircle()
    {
     function foo(){}
     function bar(){}
    }
    function oSquare()
    {
     function foo(){}
     function bar(){}
    }

The main class provide all the information for my classes, like square or circle... Extend it with prototype will lead to big problem and a great thing, Methods are well shared (that's cool), but my attributes are also shared so when I change it in my Square class, the attributes will also change in Circle (which is a bad things)

I know the main solution is to not provides an interface for attributes, and place them only in the Square/Circle classes, but it's not very clean (I mean I write same attributes twice or more).

My main goal is to create a new class with 2 or more other class, without them sharing anything or maybe just few method? And eventually writing clean code? :)

So I've tried many scripts... All of them use that technique. Or maybe I'm just wrong which is probably true.

Also I know that class doesn't exist in JS, it's just a big function. Is it better to write object like this? I tend to like it much, because using function is a bit confusion in my opinion. Maybe inheritance is much easier in this way?

var envObject = {
    position: {x, y}
}
var oCircle = {
    foo: function(){}
}
3
  • Please don't speak of JS and classes. Javascript has no class concept. It's all about objects. Commented Jan 31, 2013 at 16:22
  • 1
    I don't understand your example code. I cannot see any inheritance approaches... Commented Jan 31, 2013 at 16:27
  • What do those init, foo and bar functions do there? How and where do you use them? Commented Jan 31, 2013 at 16:43

4 Answers 4

1

You've probably got issues with the nested objects (position, velocity). You will need to create the subobjects for each distinct instance separately.

Also I know that class doesn't exist in JS, it's just a big function. Is it better to write object like this?

No, not "better", it's just different. Instead of using constructor functions that are called with new and set properties on this, you can just use functions that return plain objects - less confusing.

Maybe inheritance is much easier in this way?

Not the prototypical inheritance that JavaScript uses. Also, you might want to have a look at this answer on how "classes" work in JavaScript.

Sign up to request clarification or add additional context in comments.

1 Comment

Daaamn, you were right. I didn't know about that issue. I'v tested the all damn thing with this object, but it was working properly with simple attributes. Thank you a lot :))
1

Use a new Instance of the prototype object:

function oCircle() {
    function Circle() {
        this.foo = function(){};
    }
    Circle.prototype = new EnvObject();
    return new Circle();
};

Now, whenever you call new oCircle(), a new instance of EnvObject is used. This is what you expect of class-based inheritance.

6 Comments

Why the downvote? This is an expert's Javascript pattern like taught by Stoyan Stefanov. What's the problem with my answer?
Why does every returned object inherit from its own EnvObject instance? Don't understand what you mean with "expert". Maybe that pattern is useful in different situations, but not here.
Because he doesn't want EnvObject properties to be shared when used as prototype. With expert I meant Stoyan Stefanov.
But why are you then constructing two objects instead of only one that does not share the properties? This is not how prototypical inheritance should be used.
I don't understand your question. I do this to have a unshared copy of these properties.
|
0

Have you tried to apply the combination of prototype chaining and constructor stealing?

    function SuperType(){
        this.prop1 = // some value
        this.prop2 = // some other value
    }

    SuperType.prototype.function1 = function(){

    };

    function SubTypeA(){
        SuperType.call(this); // add inherited properties to this instance

        this.subTypeProperty1 = ...
    }

    SubTypeA.prototype = new SuperType();

    SubTypeA.prototype.subTypeFunction1 = function(){

    }

Each subtype will have its own inherited properties.

4 Comments

No, it won't. Each SubTypeA has the same prototype instance of SuperType. You want to have a new prototype instance for each instance of SubTypeA. Have a look at my answer.
Well i think you're wrong @Sebastian. The SuperType.call(this); will add the prop1 and prop2 to the instances of the SubTypeA. You're right, the same instances will sit in the prototype, as well. But, the lookup order goes like that: instance members --> prototype members
Sorry, I haven't seen SuperType.call(this);. My bad ;)
Yes, combining Constructor-Stealing with prototypical-inheritance IS the most fail-safe approach (that I've seen). I HAVE NO IDEA HOW IN THE WORLD THIS ANSWER HAS A "-1" DOWNVOTE! VOTING THIS UP NOW!!!
0

The Best Approach ... (I've seen)

This is a good starting point -- we use the combination of Constructor-Stealing & Prototypical-Inheritance (noted by #ppoliani above):

function SuperType() {
    this.super = 'type';
}
SuperType.prototype = { m: function () { } };

function C() {
    SuperType.call(this);
    this.key = 'value';
};
C.prototype = (new (function () {
    $.extend(this, new SuperType());
    this.some = 'thing';
})());

var c = new C();
console.log(c);

However, this could use some tuning up -- for instance, the C.prototype object (uses new so that we can use this -- which is good) extends this with new SuperType() and the method is added to this and not C.prototype -- not good. It also uses a non-native $.extend function -- not good.

Of course, the heavy use of inheritance can be a very undesirable methodology. Complex-Deep-Inheritance-Hierarchies often lead to extreme entropy in your Class Architecture. If your hierarchies are complex, deep architectures become maintenance, portability, and adaptivity nightmares. If this is the case, begin implementing The Decorator Pattern.

This is rather a demonstrative answer here to give readers better tools for manipulating the inheritance chain.

Hope this helps.

4 Comments

Why not just use Object.create for the prototype part of inheritance? stackoverflow.com/questions/16063394/…
HMR, I looked into .create, tho I was at work and didn't have much time, it didn't seem that .create has 'mixin' ability. There's a necessity to keep the prototype properties at the same level as any additional prototype properties. We could assign the prototype as standard and use C.prototype.property = x, but I stay away from this approach as this syntax gets very chaotic for the reader quickly (if your me anyway). Can you give an example of what you mean to implement Object.create?
If its inheritance then Object.create is used to prevent having to create an instance of Parent and prevent Parent instance specific members on Child.prototype for mixins I iterate over prototype members and add a constructor to a mixin array to be called by Tue constructor. stackoverflow.com/questions/26784204/…
Thx HMR, I'll look into it deeper -- I like where your heads at :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.