Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Не совсем корректно сравнивать реализации композиции и наследования. Ведь композицию можно сделать иначе — без пересоздания объекта на каждый чих.
function castSpell () {
console.log(`${this.name} casts ${spell}!`);
this.mana--;
}
function fight () {
console.log(`${this.name} slashes at the foe!`);
this.stamina--;
}
const fighter = (name) => ({{
name,
health: 100,
stamina: 100,
fight
})
const mage = (name) => ({
name,
health: 100,
mana: 100,
castSpell
})
const paladin = (name) => ({
name,
health: 100,
mana: 100,
stamina: 100,
fight,
castSpell
});const character = (name) => ({
name,
health: 100,
});
const fighter = (name) => ({
...character(name),
stamina: 100,
fight
})
const mage = (name) => ({
...character(name),
mana: 100,
castSpell
})
const paladin = (name) => ({
...character(name),
mana: 100,
fight,
castSpell
});найти ложку дегтя в предложенном решении...… достаточно зачерпнуть ложкой в любом месте вашего решения.
const canCast = (state) => ({
cast: (spell) => {
console.log(`${state.name} casts ${spell}!`);
state.mana - ; // <=== процедурщина
}
}) return Object.assign(
state, // <=== процедурщина
canCast(state)
); Во-первых, нафиг такое усложнение с Object.assign, которое ломает автодополнение?
Но про такую фигню статью не напишешь, да? Да и бгомеркий this, который используют только грязныё джависты. О, кстати, давайте соблюдать DRY.
const canCast = (state) => {
state.mana = 100
state.cast = function() {
console.log(`${this.name} casts fireball!`);
this.mana -- ;
}
}
const character = (state) => {
state.health = 100
}
const mage = (name) => {
let state = { name }
character(state)
canCast(state)
return state;
}
function cast() {
console.log(`${this.name} casts fireball!`);
this.mana--;
}
const canCast = (state) => {
state.mana = 100
state.cast = cast
}
// ну и как альтернатива замыканию
const boundCast = (state) => {
state.mana = 100
state.cast = cast.bind(state)
}
const canCast = (state) => {
state.cast = (spell) => {
console.log(`${state.name} casts ${spell}!`);
state.mana--;
}
}
const canFight = (state) => {
state.fight = () => {
console.log(`${state.name} slashes at the foe!`);
state.stamina--;
}
}
function FighterComp(name) {
this.name = name;
this.health = 100;
this.stamina = 100;
canFight(this);
}
function MageComp(name) {
this.name = name;
this.health = 100;
this.mana = 100;
canCast(this);
}
function Paladin(name) {
this.name = name;
this.health = 100;
this.mana = 100;
this.stamina = 100;
canCast(this);
canFight(this);
}
const allProperties = {
addCommon(state, name) {
state.name = name;
state.health = 100;
},
addMagic(state) {
state.mana = 100;
},
addFight(state, name) {
state.stamina = 100;
}
};
const allMethods = {
cast(spell) {
console.log(`${this.name} casts ${spell}!`);
this.mana--;
},
fight(spell) {
console.log(`${this.name} slashes at the foe!`);
this.stamina--;
},
};
function Mage2(name) {
allProperties.addCommon(this, name);
allProperties.addMagic(this);
}
Mage2.prototype.cast = allMethods.cast;
function Fighter2(name) {
allProperties.addCommon(this, name);
allProperties.addFight(this);
}
Fighter2.prototype.fight = allMethods.fight;
Цена композиции в Javascript-мире