How to invoke a function directly in a compositing object?

Hi community,

I use the composition to create my object rather than prototyping.

My question : is it possible to invoke directly the function “fight” in the object to avoid these extra line
player.fight()” ?

Thanks for your response.

const can_fight = (state) => ({
	fight: () => {
		console.log(`${state.name} fight!`);
		state.damage--;
	}
})

export const Player= (name) => {
	let state = {
		name,
		damage: 100,
	}
	return Object.assign(
		state,
		can_fight(state),
	);
}

let player = Player("Joe")
player.fight()

You can just call can_fight in the Player definition right before the return.

But at the end this makes not much sense for me.

What is the advantage of composing the object instead of defining a class and create an instance? For me your code is much less readable then a standard class definition, but this might be my personal meaning.

Hi Thallius,

If i invoke “fight” directly in the object, i have an error because i try to access state inside the object.

image

I prefer to use composition instead prototype because it’s more flexible with a game.

Your factory function could have been simplified a bit like your can_Fight function.

const Player = (name, damage = 100) => ({
  name,
  damage,
  ...canFight({name, damage})
})

You could call it in one line like this

Player('Joe').fight()

It seems a bad idea to me, to have your factory function invoke fight as well. I believe it should do just one job — you put something in, name, and you get something in return, an object.

I think this is the kind of pattern the OP is looking at

1 Like

Even if rpg is correct that it makes no sense to put it in the factory (What I was saying also in my first post)

I meant it that way

Hi both,

Thanks for your response.

@rpg_digital, your video describe very well the advantage of using composition instead prototyping. However, dev don’t like this solution and i don’t know why ? (I’m not a dev from the beginning :; )

@Thalius, thanks your solution help me to dot this which is a mixed solution of your two answers

const can_fight = (state) => ({
	fight: () => {
		console.log(`${state.name} fight!`);
		state.damage--;
	}
})

const Player= (name) => {
	let state = {
		name,
		damage: 100,
	}
        can_fight(state).fight();
	return {
		...state,
		...can_fight(state)
	}
	
}

let player = Player("Joe")
// Joe fight !

For me the usage of a class is much more readable. Your code would look like this

class Player
{
    name;
    damage = 100;

    constructor(name)
    {
        this.name = name;
    }
    
    fight()
    {
         this.damage—;
         console.log(this.name + „ fight!“);
    }
}

const player = new Player("Joe").fight();   

Which for me is so much more structured and clean.

1 Like

Yes i agree with you but when your code evolve it is less flexible than composition.

Yeah I agree, maybe you might just return this from fight() though to have a 1-liner initialisation:

const can_fight = (state) => ({
  fight () {
    console.log(`${state.name} fight!`)
    state.damage--
    
    return this
  }
})

const createPlayer = name => {
  const state = {
    name,
    damage: 100,
  }
  
  return { 
    ...state, 
    ...can_fight(state) 
  }
}

const player = createPlayer('Joe').fight()
// ...
1 Like

That’s an idea @m3g4p0p, I didn’t think of chaining :slight_smile:

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.