Confused about correct way of inheriting JavaScript

8

I'm looking at ways to apply Object Oriented in JavaScript. I noticed that there are several ways to do Inheritance in JavaScript. I did the one I found simple and worked. But is it really within the standards? is correct?

Follow 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 more, now I came up with the following code for Inheritance, would this be an advanced form of inheritance in JavaScript? (obs .: The extra properties created were to test the passing of 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? Thanks

    
asked by anonymous 27.11.2014 / 14:54

2 answers

6

How are you using is correct.

It may be interesting to improve some details. For example you can make the name internal property and thus be part of the human prototype:

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

So you avoid doing

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

and can only do

var pablo = new humano('Pablo');

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

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

then pablo.comer() will give you the most interesting answer.

You 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);

Normally we use large letter at the beginning of a Class name. So it should be Humano and Animal .

    
27.11.2014 / 15:09
6

As said Renan , there is no "right" way, and this solution works well in your example. But I'd like to show you another one that solves a common problem with your solution. The problem occurs when the constructor of the "superclass" 1 expects a required 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 example above, to give a% object of%, you must pass the parameters to the constructor as an object. It will give you an error if you do not pass, because the constructor code tries to access the properties of this object. Of course it is possible to treat this error within the Humano.prototype constructor, but it is not a generic solution.

There is another way to create an object that has method Animal (therefore, an object that inherits from comer ) 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 with inheritance because it does not depend on the invocation of the constructors. If your prototype chain is long and several constructors have parameters that might cause the problem I mentioned, consider using this method.

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

    
27.11.2014 / 18:24