Best way to define "private" functions

Discussion in 'Javascript' started by blackholebutterfly@gmail.com, Feb 28, 2008.

  1. Guest

    I have seen a couple of ways to define private functions inside other
    functions.

    1.
    var myFunc1 = function() {

    function myInnerFunc() {
    }
    };

    2.
    var myFunc2 = function() {

    var myInnerFunc = function () {
    };
    };

    Let's assume that both myFunc1 and myFunc2 have a "public" method also
    that calls the "private" method:
    this.init = function() {
    myInnerFunc
    };

    Is there any reason to write/define the private methods one way as
    opposed to the other? I am leaning toward using the 2nd way (using var
    myInnerFunc = ...) but I cannot give a good reason for choosing this
    way instead of the way in #1 above. (I realize that the -- this --
    keyword is unavailable in the private method using either construct.)

    As always, many thanks.
    b l a c k h o l e b u t t e r f l y
     
    , Feb 28, 2008
    #1
    1. Advertising

  2. dhtml Guest

    On Feb 27, 10:36 pm, wrote:
    > I have seen a couple of ways to define private functions inside other
    > functions.
    >
    > 1.
    > var myFunc1 = function() {
    >
    > function myInnerFunc() {
    > }
    >
    > };
    >
    > 2.
    > var myFunc2 = function() {
    >
    > var myInnerFunc = function () {
    > };
    >
    > };
    >
    > Let's assume that both myFunc1 and myFunc2 have a "public" method also
    > that calls the "private" method:
    > this.init = function() {
    > myInnerFunc
    >
    > };
    >
    > Is there any reason to write/define the private methods one way as
    > opposed to the other? I am leaning toward using the 2nd way (using var
    > myInnerFunc = ...) but I cannot give a good reason for choosing this
    > way instead of the way in #1 above. (I realize that the -- this --
    > keyword is unavailable in the private method using either construct.)
    >


    I usually prefer function declarations over function exp. Function
    declarations are parsed first so you can refer to them -- even call
    them before they appear.

    function Master() {

    this.init = pub;

    function pub() {
    var r = Math.random();
    if( r > .1 )
    randInt(r);
    };

    function randInt(r) {
    document.title = r * 10 | 0;
    }
    }

    The reason I prefer this way is that you see what the object is all
    about right at the very top. I use a closure in a similar manner for
    an exporting pattern - export at the top, function declarations below.
    I don't program in Perl, but it is similar to this pattern:
    http://perldesignpatterns.com/?ExportingPattern

    except in JavaScript.

    The other benefit to function declarations are that they have an
    identifier. With function expression, the identifier is optional and
    jscript ends up treating it like a function declaration anyway (it's a
    bug).

    I used the approach here:
    http://dhtmlkitchen.com/ape/build/dom/viewport-f.
    http://dhtmlkitchen.com/ape/build/dom/classname-f.js

    Garrett


    > As always, many thanks.
    > b l a c k h o l e b u t t e r f l y
     
    dhtml, Feb 28, 2008
    #2
    1. Advertising

  3. dhtml Guest

    On Feb 27, 11:54 pm, dhtml <> wrote:
    > On Feb 27, 10:36 pm, wrote:


    > The other benefit to function declarations are that they have an
    > identifier. With function expression, the identifier is optional and
    > jscript ends up treating it like a function declaration anyway (it's a
    > bug).


    I should qualify that:
    JScript interprets a function expression with an identifier as a
    function expression and a function declaration -- the identifier
    affects the enclosing scope.

    > > As always, many thanks.
    > > b l a c k h o l e b u t t e r f l y
     
    dhtml, Feb 28, 2008
    #3
  4. Guest

    On Feb 27, 11:57 pm, dhtml <> wrote:
    > On Feb 27, 11:54 pm, dhtml <> wrote:
    >
    > I should qualify that:
    > JScript interprets a function expression with an identifier as a
    > function expression and a function declaration -- the identifier
    > affects the enclosing scope.


    Are there any advantages to using function expressions in this
    situation? I feel like I see them all the time in code, but have never
    stopped to wonder why they might be used.
     
    , Feb 28, 2008
    #4
  5. dhtml Guest

    On Feb 28, 12:22 am, wrote:
    > On Feb 27, 11:57 pm, dhtml <> wrote:
    >
    > > On Feb 27, 11:54 pm, dhtml <> wrote:

    >
    > > I should qualify that:
    > > JScript interprets a function expression with an identifier as a
    > > function expression and a function declaration -- the identifier
    > > affects the enclosing scope.

    >
    > Are there any advantages to using function expressions in this
    > situation? I feel like I see them all the time in code, but have never
    > stopped to wonder why they might be used.


    FunctionExpressions can be used in blocks.

    This makes it possible to:

    var f;
    if(typeof document.documentElement.clientTop == "number") {
    f = function(el) {
    // using clientTop
    };
    } else if(document.defaultView &&
    document.defaultView.getComputedStyle) {
    f = function(el) {
    // using computedStyle
    };
    }
     
    dhtml, Feb 28, 2008
    #5
  6. Guest

    On Feb 28, 2:40 am, dhtml <> wrote:
    >
    > FunctionExpressions can be used in blocks.
    >


    So apart from blocks, in the situation where you have a simple "class"
    of public and private methods, isn't it true to say that using
    function declarations (for private) is less prone to error, since the
    priv. function can be called from anywhere in the class, even before
    the declaration whereas calling a func. created through assignments is
    dependent on the assignment having previously taken place?
     
    , Feb 28, 2008
    #6
  7. dhtml Guest

    On Feb 28, 7:25 am, wrote:
    > On Feb 28, 2:40 am, dhtml <> wrote:
    >
    >
    >
    > > FunctionExpressions can be used in blocks.

    >
    > So apart from blocks, in the situation where you have a simple "class"
    > of public and private methods, isn't it true to say that using
    > function declarations (for private) is less prone to error, since the
    > priv. function can be called from anywhere in the class, even before
    > the declaration whereas calling a func. created through assignments is
    > dependent on the assignment having previously taken place?


    A function declaration does allow the function to be moved around in
    source order, that is true. The errors that might be avoided -
    Reference Error - would be easy to spot even with a function
    expression.

    function C(){
    this.f = priv; // reference error.
    var priv = function() { }
    }

    So this isn't a strong argument for choosing function declaration over
    function expression.

    Stylistically, I don't like having init routines in a constructor.

    This could be accomplished with the module pattern, but would require
    moving the object's public interface to the bottom. I find this
    undesirable:

    var x = (function() {

    return { m : m }; // 2nd pass - Statement processed, return

    // first pass, c is added to variable object with value "undefined".
    var c = 23;

    // first pass, m is added to the variable object as a function.
    function m() {
    document.title = "Aika " + c;
    }
    })();

    x.m();

    The result would be title = "Aika undefined". To fix this, you could
    move the return statement to the bottom (which feels like the right
    place for a return statement) --


    var x = (function() {

    // first pass, c is added to variable object with value "undefined".
    var c = 22;

    // first pass, m is added to the variable object as a function.
    function m() {
    document.title = "Aika " + c;
    }

    return { m : m }; // 2nd pass - Statement processed, return
    })();

    x.m();

    --
    But now the returned object - the one that gets assigned to x - is
    described all the way at the bottom. Objects get bigger. If the return
    statement is all the way at the bottom, it requires scrolling through
    possibly 500+ lines just to find out what the object is about. I
    prefer to see what it's about right away. It's clearer to have the
    export right at the very top, so you see what the object is about
    first:

    var x;
    (function() { // function expression

    x = { m : m };

    var c = 24;

    function m() {
    // "private" method.
    function m_priv() { document.title = "Aika: " + c; }

    // now assign private method as property of this.
    this.m = m_priv;
    return this.m();
    }
    })();

    x.m();


    Garrett
     
    dhtml, Feb 28, 2008
    #7
  8. dhtml Guest

    On Feb 28, 12:36 pm, dhtml <> wrote:
    > On Feb 28, 7:25 am, wrote:
    >
    > > On Feb 28, 2:40 am, dhtml <> wrote:


    > A function declaration does allow the function to be moved around in
    > source order, that is true. The errors that might be avoided -
    > Reference Error - would be easy to spot even with a function
    > expression.
    >
    > function C(){
    > this.f = priv; // reference error.
    > var priv = function() { }
    >
    > }


    Actually, sorry, it's a reference error only when this.f is called.

    that is because this.f points to priv, and when the C function is
    entered, priv is initialized to undefined.

    As far as the error being "easy to spot," it seems so to me, but might
    not to someone else - so I guess I somewhat agree with your statement
    after all - using function declaration instead of a function
    expression (where it is valid to do so) would be less error prone.

    > Garrett
     
    dhtml, Feb 29, 2008
    #8
  9. dhtml wrote:
    > Stylistically, I don't like having init routines in a constructor.


    Initialization is exactly what constructor code is for.


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
     
    Thomas 'PointedEars' Lahn, Mar 1, 2008
    #9
  10. dhtml Guest

    On Mar 1, 2:57 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > dhtml wrote:
    > > Stylistically, I don't like having init routines in a constructor.

    >
    > Initialization is exactly what constructor code is for.
    >


    Putting functional code into a constructor is generally considered to
    be bad style.

    A long constructor is makes changing the code harder. This is
    especially true when trying to make a subclass. It also can be a
    source of a memory leak because its often used in a way to assign
    event handler functions to elements. In other cases, a long
    constructor is the result of setting up configuration for the object.

    function Menu(el, config){
    this.id = el.id;
    this.type = config.type;
    this.hoverClass = config.hoverClass;
    this.disabledClass = config.disabledClass.

    et c.
    }

    Long, messy. Would be better written -

    function Menu(el, config) {
    this.id = el.id;
    this._initConfig(config);
    }

    - or even -

    function Menu(el, config) {
    this.id = el.id;
    this._config = config;
    }

    The last one has different implications because the object that
    _config holds can exist after the menu instance has been destroyed.


    > PointedEars
    > --
    > Prototype.js was written by people who don't know javascript for people
    > who don't know javascript. People who don't know javascript are not
    > the best source of advice on designing systems that use javascript.
    > -- Richard Cornford, cljs, <f806at$ail$1$>
     
    dhtml, Mar 1, 2008
    #10
  11. On Feb 27, 10:36 pm, wrote:
    > I have seen a couple of ways to define private functions inside other
    > functions.
    >
    > 1.
    > var myFunc1 = function() {
    >
    > function myInnerFunc() {
    > }
    >
    > };
    >
    > 2.
    > var myFunc2 = function() {
    >
    > var myInnerFunc = function () {
    > };
    >
    > };


    I use the second option. I haven't been using function declarations
    for quite some time now because it makes the code less flexible in
    some ways. If you want to wrap the declaration in an if statement then
    the function declaration needs to be changed to an expression. If you
    want to make the function a property of some object then the
    declaration has to be converted to an expression.

    With a function declaration the declaration can come after the use of
    the function. I don't find this useful or stylistically desirable.

    When you use an inner function the inner function is defined each time
    the outer function is called. If you don't need this then using an
    inner function as above is an expensive way to create "private"
    functions. There are other ways to do it.

    var myFunc2 = (function() {
    var myInnerFunc = function() {
    //...
    };
    return function() {
    myInnerFunction();
    }
    })();

    > Let's assume that both myFunc1 and myFunc2 have a "public" method also
    > that calls the "private" method:


    This sounds very class-ish which is usually not the best way to think
    in JavaScript. That change takes time.

    > this.init = function() {
    > myInnerFunc
    >
    > };
    >
    > Is there any reason to write/define the private methods one way as
    > opposed to the other? I am leaning toward using the 2nd way (using var
    > myInnerFunc = ...) but I cannot give a good reason for choosing this
    > way instead of the way in #1 above. (I realize that the -- this --
    > keyword is unavailable in the private method using either construct.)


    You can use "this" in the inner function if you call the function with
    "Function.prototype.call" or "Function.prototype.apply". These bind
    the "this" keyword in the inner function to the first argument in the
    call.

    var myFunc2 = function() {

    var myInnerFunc = function () {
    alert(this.x); // do something with "this"
    };
    this.x = 10;
    myInnerFunc.call(this);
    };

    // Example use will cause the alert to show 10.
    ({a:myFunc2}).a();

    // or
    myFunc2.call({})

    // or
    myFunc2.apply({})

    Peter
     
    Peter Michaux, Mar 1, 2008
    #11
  12. dhtml Guest

    On Mar 1, 12:02 pm, Peter Michaux <> wrote:
    > On Feb 27, 10:36 pm, wrote:



    > I use the second option. I haven't been using function declarations
    > for quite some time now because it makes the code less flexible in
    > some ways.


    That is true. The worse thing is that browsers will let you put an FD
    (function declaration) in a block, and will behave differently.


    If you want to wrap the declaration in an if statement then
    > the function declaration needs to be changed to an expression. If you
    > want to make the function a property of some object then the
    > declaration has to be converted to an expression.
    >


    I don't see what you mean. If I want to make the function | m | a
    property of an object | x | -

    x = { m : m };
    function m() {

    }

    That's perfectly valid. Even if I put the x = {m : m} at the bottom.


    > With a function declaration the declaration can come after the use of
    > the function. I don't find this useful or stylistically desirable.


    I can see how that could look strange to others. I try to write code
    that is easy to understand (see explanation above)

    >
    > When you use an inner function the inner function is defined each time
    > the outer function is called. If you don't need this then using an
    > inner function as above is an expensive way to create "private"
    > functions. There are other ways to do it.
    >


    One of the ways is to have a function that lazily assigns the right
    method to the object it is a property of. The way it works is that if
    the function is called, it defines a function, then assigns that
    function to be the new value of the method.

    If you wanted to have conditional logic to define m_priv, then
    function expression would be only choice. The benefit would be that
    you could do the conditional checks outside of the function, which
    would tend to speed up execution of that function when it is called.

    var x;

    (function(){
    x = { m : m };

    function m() {
    var m,
    docEl = document.documentElement;

    if("pageYOffset"in window) {
    m = function() {
    return window.pageYOffset;
    };
    } else if("scrollTop"in docEl) {
    m = function() {
    return docEl.scrollTop;
    };
    }
    this.m = m;
    return this.m();
    }
    })();
    x.m();

    The disadvantage to that is when | x.m | gets renamed to something
    more meaningful (x.q, for example), then |this.m = m_priv;| must also
    change to |this.q = m_priv;|. It's an ugly dependency that I would
    rather avoid.

    [snip about call/apply]

    > Peter
     
    dhtml, Mar 2, 2008
    #12
  13. VK Guest

    On Mar 1, 10:16 pm, dhtml <> wrote:
    > function Menu(el, config){
    > this.id = el.id;
    > this.type = config.type;
    > this.hoverClass = config.hoverClass;
    > this.disabledClass = config.disabledClass.
    >
    > et c.
    >
    > }
    >
    > Long, messy. Would be better written -
    >
    > function Menu(el, config) {
    > this.id = el.id;
    > this._initConfig(config);
    >
    > }
    >
    > - or even -
    >
    > function Menu(el, config) {
    > this.id = el.id;
    > this._config = config;
    >
    > }


    So what is the gain of this approach? You just moved your "mess" from
    one place to another. Whatever has to be inited - it has to be inited,
    so no matter how many "initConfig" you are using, you still have to
    start the actual this.something = something.
    Whatever is special to this particular class of objects, it has to be
    assigned right in the constructor, whatever is inherited from its
    supers must be already here either over the prototype chain or over
    super.call(this)
     
    VK, Mar 2, 2008
    #13
  14. dhtml wrote:
    > On Mar 1, 2:57 am, Thomas 'PointedEars' Lahn <> wrote:
    >> dhtml wrote:
    >>> Stylistically, I don't like having init routines in a constructor.

    >> Initialization is exactly what constructor code is for.

    >
    > Putting functional code into a constructor is generally considered to be
    > bad style.


    By whom?

    > A long constructor is makes changing the code harder.


    Non sequitur. Initialization code can be short.

    > This is especially true when trying to make a subclass.


    There are no classes, so no subclasses. And for constructors of derived
    prototype objects, that is simply not true.

    > It also can be a source of a memory leak because its often used in a way
    > to assign event handler functions to elements.


    Non sequitur. Memory leaks can occur everywhere; the important thing is how
    try to avoid them. (This is described in the FAQ Notes.)

    But, as we have discussed before, it can certainly be useful to define an
    object's method to be created in the constructor instead of inherited from
    the prototype object. One possibility that readily springs to mind is a
    method as a closure defined by the constructor arguments.

    > In other cases, a long constructor is the result of setting up
    > configuration for the object.


    Long constructors are a product of your imagination.

    > [...]


    Sorry, I don't see the distinct advantage in your approach.


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
     
    Thomas 'PointedEars' Lahn, Mar 2, 2008
    #14
  15. dhtml wrote:
    > function Menu(el, config){
    > this.id = el.id;
    > this.type = config.type;
    > this.hoverClass = config.hoverClass;
    > this.disabledClass = config.disabledClass.
    >
    > et c.
    > }
    >
    > Long, messy. Would be better written


    .... for example so:

    function Menu(el, config)
    {
    for (var p in config)
    {
    this[p] = config[p];
    }

    this.target = el;
    }

    Incidentally, I am currently using that pattern in a project of mine.

    > function Menu(el, config) {
    > this.id = el.id;
    > this._initConfig(config);


    So that's only two lines less now in the constructor (none if you remove the
    whitespace). Do you still think it's worth it in this case?

    > }
    >
    > - or even -
    >
    > function Menu(el, config) {
    > this.id = el.id;
    > this._config = config;
    > }
    >
    > The last one has different implications because the object that
    > _config holds can exist after the menu instance has been destroyed.


    Non sequitur. It keeps existing (until marked for garbage collection) with
    any of the presented approaches. Apparently you have failed to recognize
    that such an assignment never copies an object, but defines another
    reference to it.

    It would only make sense to say that the object keeps existing after all
    references in the calling execution contexts have been removed.


    Please trim your quotes, especially don't quote signatures. ISTM you have
    been told that several times before.


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
     
    Thomas 'PointedEars' Lahn, Mar 2, 2008
    #15
  16. Peter Michaux wrote:
    <snip>
    > With a function declaration the declaration can come after
    > the use of the function. I don't find this useful or
    > stylistically desirable.


    Just because a function declaration can come after the use of that function
    does not mean you have to write your code in that way. It is a commonly
    proposed 'best practice' for the layout of code in, say, function bodies to
    mirror how that code will be handled. That is, to place inner function
    declarations and variable declarations at the beginning of a function body,
    in order to reflect the fact that they will be acted upon before the
    execution of any function body code. If that practice were followed then
    uses of declared functions would always occur after their declarations.

    <snip>
    > You can use "this" in the inner function if you call the
    > function with "Function.prototype.call" or
    > "Function.prototype.apply". These bind the "this" keyword
    > in the inner function to the first argument in the call.

    <snip>

    The term "bind" seems inappropriate and potentially misleading here as it
    implies some sort of semi-permanent or long term association, while the -
    call -and - apply - methods only set the - this - value for the single
    function call in question.

    Richard.
     
    Richard Cornford, Mar 2, 2008
    #16
  17. dhtml Guest

    On Mar 2, 5:28 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > dhtml wrote:


    >
    > Non sequitur. It keeps existing (until marked for garbage collection) with
    > any of the presented approaches. Apparently you have failed to recognize
    > that such an assignment never copies an object, but defines another
    > reference to it.
    >


    In the first two examples, the properties were copied. The menu did
    not have a _config object.

    function Menu(el, config){
    this.id = el.id;
    this.type = config.type;
    this.hoverClass = config.hoverClass;
    this.disabledClass = config.disabledClass;
    }

    var c = { type: "sticky", id : "blah", hoverClass : "hover",
    disabledClass : "disabled" },
    m = new Menu({}, c);

    m has its configuration properties copied over from the config object
    (config.type, hoverClass, et c). When the menu is destroyed, those
    properties (in this case) can't exist anymore.

    The same is not true by assigning this.config = config.

    The decision to use composition vs. aggregation comes up when
    refactoring a long parameter list. This usually leads to an init
    routine of some sort. Having an init routine in the constructor is
    generally considered bad taste. If you're looking for external sources
    on those, Refactoring [Fowler] (long parameter list), Head First OOA&D
    (only for the explanation of composition/aggregation and delegation).

    Garrett

    > PointedEars
     
    dhtml, Mar 2, 2008
    #17
  18. dhtml wrote:
    > [...] Thomas 'PointedEars' Lahn [...] wrote:
    >> Non sequitur. It keeps existing (until marked for garbage collection)
    >> with any of the presented approaches. Apparently you have failed to
    >> recognize that such an assignment never copies an object, but defines
    >> another reference to it.

    >
    > In the first two examples, the properties were copied.


    You miss the point. I was talking about the object itself. And while the
    properties are in a way "copied" in the first example, that does not mean
    anything for the property values. See below.

    > The menu did not have a _config object.


    You don't say!

    > [...] m has its configuration properties copied over from the config
    > object (config.type, hoverClass, et c). When the menu is destroyed, those
    > properties (in this case) can't exist anymore.
    >
    > The same is not true by assigning this.config = config.


    It is pretty much the same. As `config' does not need to be an object
    reference, its properties do not need to be primitive values.

    > The decision to use composition vs. aggregation comes up when refactoring
    > a long parameter list. This usually leads to an init routine of some
    > sort. Having an init routine in the constructor is generally considered
    > bad taste.


    You are mistaken. It depends very much on the task to be accomplished.

    > If you're looking for external sources on those, Refactoring [Fowler]
    > (long parameter list), Head First OOA&D (only for the explanation of
    > composition/aggregation and delegation).


    That's only two resources you cite, of which probably none deals with
    ECMAScript in particular, and you actually consider that "generally".

    Besides, the question of composition vs. aggregation does not apply to this
    situation, it is rather a matter of what one wants to achieve and of
    efficiency. ISTM you are confusing object composition with function
    composition.


    PointedEars
    --
    Use any version of Microsoft Frontpage to create your site.
    (This won't prevent people from viewing your source, but no one
    will want to steal it.)
    -- from <http://www.vortex-webdesign.com/help/hidesource.htm>
     
    Thomas 'PointedEars' Lahn, Mar 2, 2008
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David WOO
    Replies:
    12
    Views:
    766
    Julie
    Mar 5, 2004
  2. vizcayno
    Replies:
    13
    Views:
    459
    Frank Millman
    Jan 9, 2007
  3. John Goche
    Replies:
    10
    Views:
    774
    Marcus Kwok
    Dec 8, 2006
  4. Kenneth McDonald
    Replies:
    4
    Views:
    309
    Bjoern Schliessmann
    Sep 2, 2007
  5. Chris Gordon-Smith
    Replies:
    20
    Views:
    919
    Daniel Pitts
    May 29, 2008
Loading...

Share This Page