문제

I have looked through all the other (excellent) answers on SO (especially this: How do JavaScript closures work?) but I wanted your feedback on my understanding of the concept.

I understand that one use case is to hide the implementation of private methods from public access.

The other one that I think of is having it as a factory generator:

<script>

function carFactory( make ) {

    var m = make;
    return { manufacture: function ( model ) 

        {console.log("A " + m + " " + model + " has been created");}

    }
}

toyotaFactory = carFactory("toyota");
hondaFactory = carFactory("honda");

toyotaFactory.manufacture("corolla");
toyotaFactory.manufacture("corolla");
hondaFactory.manufacture("civic");

</script>

This outputs:

A toyota corolla has been create
A toyota corolla has been created
A honda civic has been created 

So do you think its a valid use case for closures (i.e. creating multiple factories using the same code base)? Or can I achieve the same thing using something much better?

Please note that the question is less about the technical implementation of closures and more about valid use cases in application design / development.

Thanks.

도움이 되었습니까?

해결책

Yes, keeping variables private is a valid use for a closure. It allows you to have private access to a variable without making it a public member.

See this reference for other examples: http://www.crockford.com/javascript/private.html

다른 팁

If I'm understanding your question correctly, you aren't concerned with keeping the make property private? If that's the case, then a closure isn't really necessary, and you could achieve the same functionality using a prototype...

function carFactory(model){
  this.m = make;
}

carFactory.prototype.manufacture = function(model){
  console.log('A ' + this.m + ' ' + model + ' has been created');
}

Which has associated performance benefits (reduced memory and increased speed), as per this question.

Closures are extremely powerful construct, with a lot of useful uses. The one you used there is actually kind of a "hack". The most common use for closures, is when you have implemented some functionality that "does something" in the middle... And that "does something" can be configured to more or less whatever you want... For example the jQuery ajax functionality can "do something" when the request has an error, or when it succed, etc... If you didn't have closures, you'd only be able to pass a "statically defined" function, which will probably need to gather the context needed to do whatever you want it to do from global variables, or you'll have to use the same signature for all functions like what it's done in C or C++ like function (customData) {} ... Closures allows you to "dynamically build functions" at runtime, reteining the context that they have when they were created, so you can pass to the modules that need to "do something" nearly anything you want, in a really easy way (in contract with what you'd do in c or c++ or without closures, that it's ugly, error prone, and a hack too).

So whenever you must "configure" some custom functionality inside something, you'll use a closure...

I was trying to come up with a practical example of information-hiding/encapsulation and this is what my attempt so far

'use strict';

const bank = (accountHolderName, initialDeposit) => {
    let balance = initialDeposit;
    const add = (amount) => {
        balance += amount;
    }

    let subtract = (amount) => {
        balance -= amount
    }

    let printBalance = () => {
        console.log(accountHolderName, "has balance of", balance, "dollars");
    }

    return {
        credit: add,
        debit: subtract,
        balance: printBalance
    }
}

let amy = bank("Amy", 1000);
amy.balance();
amy.credit(100);
amy.balance();
amy.debit(10);
amy.balance();

let sam = bank("Sam", 50);
sam.balance();
sam.credit(50);
sam.balance();
sam.debit(100);
sam.balance();

Once you run, you would get the following output

Amy has balance of 1000 dollars
Amy has balance of 1100 dollars
Amy has balance of 1090 dollars
Sam has balance of 50 dollars
Sam has balance of 100 dollars
Sam has balance of 0 dollars

The benefits?

  • the balance variable is not directly accessible.
  • Using closures, every caller get's their own data. Amy's balance is not interfering with Sam's data
  • The callers (Amy, Sam, and others) has a nice API to work with instead of worrying about the internal details on how bank operates.

Am I missing something else?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top