Reputation: 125
I wrote this snippet of code, trying to create an impromptu fighting game. It uses the old style function keyword, therefore when I want to use a helper function isAlive I'm forced to do a very ugly 'this' binding.
I'm trying to grasp how 'this' behaves differently with arrow functions but when I change the first line to ES6 syntax and drop the binding it always returns false.
let isAlive = () => this.health > 0;
What am I doing wrong? I'm pretty sure the syntax itself is OK.
let isAlive = function () { return this.health > 0};
let getFighter = function (color, strength) {
return {
color: color,
health: 100,
strength: typeof strength !== 'undefined' ? strength : 1,
attack: function (what) {
hit_points = Math.floor(Math.random() * 10 * this.strength);
document.writeln(this.color + ' fighter attacks ' + what.color + ' trying to deal ' + hit_points + ' damage.');
what.get_hurt(hit_points);
},
get_hurt: function (hit_points) {
if ( !isAlive.bind(this)() ) {
document.writeln(this.color + ' fighter already dead!');
document.writeln();
return;
}
this.health = this.health - hit_points;
document.writeln(this.color + ' received ' + hit_points + ' damage and has ' + this.health + ' HP left.');
if ( !isAlive.bind(this)() ) {
document.writeln(this.color + ' fighter died!');
}
document.writeln();
}
};
};
blue = getFighter('Blue', 3);
red = getFighter('Red');
console.log(red);
console.log(blue);
while (isAlive.bind(blue)()) {
red.attack(blue);
}
red.attack(blue)
Upvotes: 2
Views: 58
Reputation: 1
You can define a parameter at isAlive
function and pass the object or this
to the function
let isAlive = ({health}) => health > 0;
let getFighter = function(color, strength) {
return {
color: color,
health: 100,
strength: typeof strength !== 'undefined' ? strength : 1,
attack: function(what) {
hit_points = Math.floor(Math.random() * 10 * this.strength);
document.writeln(this.color + ' fighter attacks ' + what.color
+ ' trying to deal ' + hit_points + ' damage.');
what.get_hurt(hit_points);
},
get_hurt: function(hit_points) {
if (!isAlive(this)) {
document.writeln(this.color + ' fighter already dead!');
document.writeln();
return;
}
this.health = this.health - hit_points;
document.writeln(this.color + ' received ' + hit_points
+ ' damage and has ' + this.health + ' HP left.');
if (!isAlive(this)) {
document.writeln(this.color + ' fighter died!');
}
document.writeln();
}
};
};
blue = getFighter('Blue', 3);
red = getFighter('Red');
console.log(red);
console.log(blue);
while (isAlive(blue)) {
red.attack(blue);
}
red.attack(blue);
console.log(red);
console.log(blue);
Upvotes: 0
Reputation: 1633
Looking at your code example, I think we first need to understand how this
works. this
is will refer to your object/function that has been instantiated.
const getFighter = function(color, strength) {
this.color = color;
this.strength = strength && 1;
return {
health: 100,
isAlive: this.health > 0,
hit_points: () => Math.floor(Math.random() * 10 * this.strength),
attack: (what) => {
document.writeln(`${this.color} fighter attacks ${what.color} trying to deal ${this.hit_points} damage.`);
what.get_hurt(this.hit_points);
return null;
},
get_hurt: () => {
if (!this.isAlive) {
document.writeln(`${this.color} fighter already dead!`);
return;
}
this.health = this.health - this.hit_points;
document.writeln(`${this.color} received ${this.hit_points} damage and has ${this.health} HP left.`);
if (!this.isAlive) {
document.writeln(`${this.color} fighter died!`);
}
},
};
};
const BlueFighter = new getFighter("Blue", 3);
const RedFighter = new getFighter("Red");
console.log('is Alive', BlueFighter.isAlive);
console.log('Health:', RedFighter.health);
You can see I take advantage of () =>
so that I can have access to this
within the function. You wouldn't get this with a regular function unless you .bind(this)
!
Upvotes: 1
Reputation: 10967
An arrow function does not create its own this, the this value of the enclosing execution context is used.
By defining isAlive in a different execution context, you also bind the keyword to a different this.
If you want to take advantage of arrow functions, than declare them inside your function
function foo(){
const isAlive = () => this.health > 100;
}
In your case, if you want a helper you either declare it as a part of the object, or uses ES6 Classes and class properties will do that for you.
Upvotes: 2