Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #20028

Re: Call within return ({})()

Message-ID <1941338.xSU4HxP9mg@PointedEars.de> (permalink)
From Thomas 'PointedEars' Lahn <PointedEars@web.de>
Organization PointedEars Software (PES)
Date 2013-05-29 11:36 +0200
Subject Re: Call within return ({})()
Newsgroups comp.lang.javascript
References <jOednf-vOIXsujjMnZ2dnUVZ_tOdnZ2d@westnet.com.au> <65f091a4-6f08-4794-b468-0f743566441c@g8g2000yqa.googlegroups.com>

Show all headers | View raw


Scott Sauyet wrote:

> Andrew Poulos wrote:
>> var myfunc = (function() {
>>
>>   // Is there a way to call 'foo' from here?
>>
>>   return {
>>     foo: function() {
>>       ...
>>     }
>>   }
>>
>> }(();
> 
> No, not if that code is running as it looks to be when the outer
> function is invoked.  `foo` has not yet been defined.  But you can
> restructure it like this:
> 
>     var myfunc = (function() {
>        function foo() {
> ...
> }
> 
> // You can easily call foo from here.
> 
>     return {
> foo: foo
>     }
>     }(();
> 
> And of course this means that the local name doesn't have to be the
> same name as the exposed one, which can sometimes be useful if you're
> trying to return something with an API you don't particularly like for
> local names.  […]

I have found it even more useful for memory-efficient aliases (backwards 
compatibility) –

  var foo = (function () {
    function _baz (…)
    {
      …
    }

    return {
      bar: _baz,
      bla: _baz
    };
  }());

– and for having rather easily maintainable, runtime-efficient 
interdependent methods without regard to definition order, due to additional 
closures:

  var foo = (function () {
    function _bar ()
    {
      … _baz() …
    }

    function _baz (…)
    {
      … _bar() …
    }

    return {
      bar: _bar,
      baz: _baz
    };
  }());

and

  var foo = (function () {
    function _bar ()
    {
      … _baz() …
    }

    function _baz (…)
    {
      … _bar() …
    }

    return {
      baz: _baz
      bar: _bar,
    };
  }());

vs.

  foo.bar = (function () {
    /* FIXME: foo.baz is still undefined here */
    var _baz = foo.baz;

    return function (…) {
      … _baz() …
    };
  }());

  foo.baz = function (…) {
    … _bar() …
  };

and

  foo.baz = function (…) {
    … _bar() …
  };

  foo.bar = (function () {
    /* NOTE: This works, but what if foo.baz needs to use foo.bar? */
    var _baz = foo.baz;

    return function (…) {
      … _baz() …
    };
  }());

The latter problem was the main reason why I have started converting JSX to 
the module pattern, where I am declaring local functions or assign 
references to them to local variables when aliases or method interdependency 
are needed.  The other reason was that thanks to a Stack Overflow answer I 
found out how to document the module pattern in a way that – apparently – 
works well with Eclipse JSDT's Outline View:

/**
 * @type jsx.object
 * @memberOf __jsx.object
 * @namespace
 */
jsx.object = (/** @constructor */ function () {
  // …

  var jsx_object = {
    /**
     * @memberOf jsx.object
     */
    …
  };

  return jsx_object;
}());

(The only drawback is that methods are recognized as non-function properties 
then.  But at least they are listed in the proper context.)

It should be noted that this suggests storing the values of non-function 
properties in local variables, and referring to those variables, for maximum 
efficiency.

Of course, this poses a challenge for code documentation as you would want 
the inline documentation before the function, and you would want it also for 
the function-property that refers to it.  My JSdoc™ shall solve this problem 
as well because apparently jsdoc-toolkit cannot.

It also means that as the number of the properties of the returned Object 
instance increases, the function declaration/expression and the property 
declaration to refer to it grow further apart; an IDE/editor with split view 
or easy word/identifier search (like Eclipse JSDT or Vim) becomes 
increasingly useful.

Finally it means that you have to forfeit backwards compatibility to 
implementations of ECMAScript before Edition 3 and to JavaScript 1.0, which 
is why applications like the ECMAScript Support Matrix which should be 
backwards-compatible must either use a different version of the pertinent 
libraries, to which changes in the original must be backported, or ignore 
some of those earlier implementations (I have opted for the former for the 
time being, which made me postpone the release of the next version last 
year).

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

Back to comp.lang.javascript | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Call within return ({})() Andrew Poulos <ap_prog@hotmail.com> - 2013-05-29 07:53 +1000
  Re: Call within return ({})() Scott Sauyet <scott.sauyet@gmail.com> - 2013-05-28 15:45 -0700
    Re: Call within return ({})() Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-05-29 11:36 +0200
  Re: Call within return ({})() JJ <duh@nah.meh> - 2013-05-29 11:55 +0700

csiph-web