Definindo uma classe em JavaScript:
var Person = function(name, email) {
this.name = name;
this.email = email;
// 1 possible way to define a "composite property"
Object.defineProperty(this, "nameWithEmail", {
get: function() {
return this.name + " <" + this.email + ">";
}
});
// I think a simpler way might be to just use a function (see `toString`)
};
// things defined under prototype will be "shared/inheried" by all classes,
// as opposed to name and email for example
Person.prototype.sayHi = function() {
console.log("Hello, my name is " + this.toString());
};
Person.prototype.toString = function() {
return this.name + " <" + this.email + ">";
};
Agora, podemos estender a classe Person:
// we define the object properties in the constructor function
var Employee = function(name, email, position) {
Person.call(this, name, email); // calling person constructor: something like super() in other languages
this.position = position;
};
// extend the Employee class with Person
Employee.prototype = Object.create(Person.prototype);
// override some functions
Employee.prototype.sayHi = function() {
Person.prototype.sayHi.call(this);
console.log("I am a " + this.position);
};
Uma alternativa: com underscore.js
// instead of
// Employee.prototype = Object.create(Person.prototype);
_.extend(Employee.prototype, Person.prototype);
Com o underscore.js, também podemos fazer herança múltipla facilmente
_.extend(Employee.prototype, Person.prototype);
_.extend(Employee.prototype, {
doSomething: function() { ... }
});
Não parece fazer mais a cadeia de protótipos. No entanto, quando você console.log()
cria os protótipos, parece que aquele com JS puro é mais limpo do que a versão de sublinhado (menos métodos extras, etc.). Eu postei uma pergunta no StackOverflow sobre isso.