Confused about the correct form of Inheritance in Javascript

Asked

Viewed 245 times

9

I am studying ways to apply Object Orientation in Javascript. I realized that there are several ways to do Inheritance in Javascript. I did the one that I thought was simple and worked. But is it really within the standards? Is it correct?

Follows the Code:

    function humano(){
        var nome;
        this.pensar = function(){
            return "Estou pensando";
        }

    }

    function animal(){
        this.comer = function(){
            return "Vou COMER!";
        }
    }


    humano.prototype = new animal();

    var pablo = new humano();
    pablo.nome = "Pablo";

    console.log(pablo.pensar());
    console.log(pablo.comer());
    console.log("Meu nome é " + pablo.nome);

Studying further, I have now arrived at the following code for Inheritance, would this be an advanced form of inheritance in Javascript? (Obs.: The extra properties created were to test the passage of the properties by inheritance)

    var obj = {};
    var coisa = {
        nome: 'Rafael',
        idade: '35'
    };

    obj.y = 55;

    Object.defineProperty(obj,'x',{value: 1, writable: false, enumerable: false, configurable: true});

    Object.defineProperty(obj,'x',{get: function(){ return obj.y}});

    Object.defineProperty(Object.prototype,"extend",{
        writable: true,
        enumerable: false,
        configurable: true,
        value: function(o){

            var names = Object.getOwnPropertyNames(o);

            for(var i = 0; i < names.length; i++ ){
                if(names[i] in this) continue;

                var desc = Object.getOwnPropertyDescriptor(o,names[i]);

                Object.defineProperty(this,names[i],desc);
            }
        }
    })

    obj.extend(coisa);
    coisa.extend(obj);

What is the best way? Thank you

  • 1

    There is no "correct" form. There is the most appropriate one for each case. To make inheritance by determining that the prototype of a function is an object is common and there is nothing wrong with it. If you solved the problem for your example simply, then it is valid.

  • 1

    Just one more thing. The variable nome in function humano is lost forever after the function is performed. It is not part of the human prototype, nor of a closure, nor the returned object. When you call your human Pablo, you create a new property in the object. Then you can discard this var nome hassle-free.

  • 2

    Search for be in no hurry to accept an answer. I was about 10 minutes writing a very complete one, but I don’t think I’ll even post more... P

  • 1

    Are we here to get our answers accepted? Or to help the community? But I’m still grateful for your 10 minutes @mgibsonbr. Thank you very much

  • @Michaelalves There is good material right here at Sopt explaining heritage in Javascript. I was compiling and contextualizing your particular case. But if you’re satisfied with what you’ve received so far, there’s no point in me continuing. I leave this link as a reference if you want to know more: http://answall.com/q/15239/215 P.S. This is also good: http://answall.com/q/30718/215

  • 1

    @mgibsonbr I would like to see your answer! Although I agree that one should wait a while to accept a kkkk answer

  • @mgibsonbr I was also curious as to what you were going to say... It would happen to have to do with what I put in my reply?

  • @mgibsonbr I also got curious :P If you are still in the cache put. Your answers are usually worth reading!

  • The question is not my answer, I was just indicating to AP that he could generally receive better answers if he waited longer to accept one (it depends on the type of question). Not so much because of the possibility of the answer being accepted, but because it is an indication that the PA is satisfied and may not even return to that question. As for what I was going to write, it’s no big deal, if it was I would have gone ahead and posted anyway... :)

  • @bfavaretto Your answer partly covers what I was going to say (less memory is spent putting the methods in the prototype than in the instance itself, if there are many objects), and the other part refers to the use of the var nome in the constructor - which is not incorrect (there are use cases for this) but it would have a different effect than intended. It was an explanation of how the prototyping chain works - something that can be found in the other referenced questions.

Show 5 more comments

2 answers

7

Like said Renan, there is no "correct" way, and this solution works well in your example. But I would like to show another that solves a common problem of your solution. The problem occurs when the constructor of the "superclass" 1 expects a mandatory parameter. For example:

function Animal(caracteristicas) {
    this.classe = caracteristicas.classe
    this.patas = caracteristicas.patas
}
Animal.prototype = {
    comer: function() {}
}

function Humano() {
    // ...
}
Humano.prototype = new Animal({
    classe: "mamíferos",
    patas: 2
});

In the above example, to display an object Humano.prototype it is necessary to pass the parameters to the constructor as object. It will give error if you do not pass, because the constructor code tries to access the properties of this object. Of course it is possible to handle this error within the constructor Animal, but it is not a generic solution.

There is another way to create an object that has the method comer (therefore, an object that inherits from Animal.prototype) without invoking the constructor, avoiding the problem:

function Humano() {
    // ...
}
Humano.prototype = Object.create(Animal.prototype);
var pessoa = new Humano();
pessoa.comer(); // funciona!

This is a more flexible way of working the inheritance, because it does not depend on the invocation of the builders. If your prototype chain is long and several constructors have parameters that can cause the problem I mentioned, consider using this method.


(1) It is not exactly superclass in JS, since the language uses prototypical heritage.

6


How you’re using it is right.

It might be interesting to work out a few details. For example, it can make the name internal property and thus be part of the human prototype:

function humano(nome) {
    this.nome = nome; 

So avoid doing

var pablo = new humano();
pablo.nome = "Pablo";  // aqui a propriedade "nome" é local ao pablo, e não a outros humanos

and can do only

var pablo = new humano('Pablo');

The same applies to what he’s eating, for example.
Passing food as argument here:

function animal(comida) {
    this.comer = function () {
        return "Vou comer " + comida + "!";
    }
}

then pablo.comer() will give more interesting answer.

Could still make this.comida a method that keeps what he eats. For example:

function animal() {
    this comida = function (comida){
        this.comer = 'Eu gosto de ' + comida;
    }
}

Take a look at the example below:

function Humano(nome) {
    this.nome = nome; 
    this.pensar = function () {
        return "Estou pensando";
    }

}

function Animal() {
        this.comida = function (comida){
            this.comer = 'Eu gosto de ' + comida;
        }
}

Humano.prototype = new Animal();
var pablo = new Humano('Pablo');
var coelho = new Animal();

pablo.comida('Lasanha');
coelho.comida('Cenoura');

console.log(pablo.pensar());
console.log(pablo.comer);
console.log("Meu nome é " + pablo.nome);
console.log(coelho.comer);

We usually use large letter at the beginning of a class name. This should be the case Humano and Animal.

  • Your answer, in my opinion is very good, would only change one thing: your animal object does not need to be initialized with a "food", for me this does not make sense. Food should be a parameter of eating functionAs the way you did, your pet would always eat lasagna... rsrsr

  • Reinaldo you’re right, Rabbits may not like Lasagna :) It was an example and can be improved. I will improve thanks. (and you can delete this answer in the meantime)

  • @Reinaldooliveira I converted your reply to comment. I’m sorry for the loss of the points, but it turns out you have enough knowledge to recover them very quickly by posting other answers ;)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.