Closures

In my last post I promised I'd show you how to create an object with private variables and methods.

Here's how you do it:

var character = (name, att, def, hp) => {  
    var between_0_and = (number) => Math.floor(Math.random() * number)
    return ({
        name: () => name,
        def: () => def,
        hp: hp,
        attack: function (enemy) {
            enemy.hp -= between_0_and(att) - between_0_and(enemy.def())
        }
    })
}

Our factory function is now returning an object that technically doesn't have a name, or the att and def stats. But the name and def methods still have access to the parameters name, and def. And the attack method has access to the att parameter.

Because the returned object's methods reference variables and functions local to the function that returns it, but outside itself, those variables and functions get to live on after the function returns. This is called a closure.

You can think of between_0_and as a private method, and the variables name, att, def as private members.

This doesn't just work for objects either. Remember this?

var power_function_maker = (power) => (number) => Math.pow(number, power)

var power_4 = power_function_maker(4)

console.log(power_4(2))  

power_function_maker returns a function that uses a closure to maintain access to power, which is a variable local to power_function_maker. power lives on, even though power_function_maker has returned.

And, again, because I couldn't help myself, here is the game code that takes our updated object:

for(var i = 0; i < 10; i++) {  
    let player = character('Eldrith The Large', 2, 2, 15)
    let monster = character('the goblin', 5, 1, 5)

    while (player.hp > 0 && monster.hp > 0) {
        player.attack(monster)
        monster.attack(player)
    }
    if(monster.hp > 0) {
        console.log(`${monster.name()} wins!`)
    } else if(player.hp > 0) {
        console.log(`${player.name()} wins!`)
    } else {
        console.log(`both ${player.name()} and ${monster.name()} are losers!`)
    }

    monster.hp = 10
    player.hp = 10
}

BTW, ES2015 has another way for you to create objects, one more familiar to programmers in other languages, classes. You can learn more about them here.

Looking for a software developer?