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


Groups > comp.lang.javascript > #22245 > unrolled thread

Anonymous self-invoking function

Started by"Robert Crandal" <noreply2me@yahoo.com>
First post2013-12-06 18:39 -0700
Last post2013-12-09 00:15 +0100
Articles 14 — 6 participants

Back to article view | Back to comp.lang.javascript


Contents

  Anonymous self-invoking function "Robert Crandal" <noreply2me@yahoo.com> - 2013-12-06 18:39 -0700
    Re: Anonymous self-invoking function Eric Bednarz <bednarz@fahr-zur-hoelle.org> - 2013-12-07 03:52 +0100
      Re: Anonymous self-invoking function "Robert Crandal" <noreply2me@yahoo.com> - 2013-12-07 12:31 -0700
        Re: Anonymous self-invoking function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-12-08 00:17 +0100
          Re: Anonymous self-invoking function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-12-08 01:08 +0100
            Re: Anonymous self-invoking function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-12-08 19:41 +0100
            Re: Anonymous self-invoking function jaranmclarn@gmail.com - 2013-12-08 12:21 -0800
          Re: Anonymous self-invoking function "Robert Crandal" <noreply2me@yahoo.com> - 2013-12-09 01:14 -0700
            Re: Anonymous self-invoking function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-12-10 15:38 +0100
    Re: Anonymous self-invoking function Bjoern Hoehrmann <bjoern@hoehrmann.de> - 2013-12-07 12:28 +0100
      Re: Anonymous self-invoking function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-12-07 12:57 +0100
    Re: Anonymous self-invoking function Joao Rodrigues <groups_jr-1@yahoo.com.br> - 2013-12-07 16:51 -0200
    Re: Anonymous self-invoking function jaranmclarn@gmail.com - 2013-12-08 12:17 -0800
      Re: Anonymous self-invoking function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-12-09 00:15 +0100

#22245 — Anonymous self-invoking function

From"Robert Crandal" <noreply2me@yahoo.com>
Date2013-12-06 18:39 -0700
SubjectAnonymous self-invoking function
Message-ID<RP-dneojCe_X4T_PnZ2dnUVZ5sWdnZ2d@giganews.com>
I'm studying some code in one of John Resig's books.
Here is a shortened/modified sample:

/* Anonymous self-invoking function */
(function() {
  this.assert = function assert(a,b) { /* code here */  };
  this.test = function test(a, b) { /* code here */ };
})();

/* Code for a testing environment or "test groups" */
window.onload = function() {
  test("Test one.", function() {
    assert(true, "Success!");
  });
}

So, it's my understanding that the properties "this.assert"
and "this.test" defined above are publicly accessible functions.
(Since the "var" keyword is missing this makes them
properties of the global window object, right?).

I don't fully understand why the self-invoking anonymous function
is needed above.  Is there a benefit to defining the functions above,
such as, "this.assert = function(a,b) {};" inside of the anonymous
function??  Global functions seem to be defined here, so why not
just define them the old-school way, such as:

function assert(a,b) {
    /* code here */
{

function test(a,b) {
    /* code here */
}

???

Robert

[toc] | [next] | [standalone]


#22246

FromEric Bednarz <bednarz@fahr-zur-hoelle.org>
Date2013-12-07 03:52 +0100
Message-ID<m28uvxcqyd.fsf@nntp.bednarz.nl>
In reply to#22245
"Robert Crandal" <noreply2me@yahoo.com> writes:

> I'm studying some code in one of John Resig's books.

Although the combination of author and group you posted to is unlikely
to yield productive answers, you should at least provide the book title
and the chapter (ebooks make page numbers problematic).

> Here is a shortened/modified sample:

In any case you should explain exactly what you shortened and/or
modified.

> /* Anonymous self-invoking function */
> (function() {
>   this.assert = function assert(a,b) { /* code here */  };
>   this.test = function test(a, b) { /* code here */ };
> })();
>
> /* Code for a testing environment or "test groups" */
> window.onload = function() {
>   test("Test one.", function() {
>     assert(true, "Success!");
>   });
> }
>
> So, it's my understanding that the properties "this.assert"
> and "this.test" defined above are publicly accessible functions.

They are properties of the global object (unless that production is
contained in ES5 strict mode code; the publication might predate ES5,
or not, who knows). Saying "they are [...] functions" is like saying
"food vouchers are nutritious".

> (Since the "var" keyword is missing this makes them
> properties of the

They are *explicitly* set as object properties (assuming `this` is in
fact not undefined).

> global window object, right?).

You want to remove `window` from that.

> I don't fully understand why the self-invoking anonymous function
> is needed above.  Is there a benefit to defining the functions above,
> such as, "this.assert = function(a,b) {};" inside of the anonymous
> function??

The most common use case would be creating an execution context for
'private' variables and/or functions that are visible to the functions
that are referenced by the global properties.

Technically, you can delete those properties (unlike variable and
function declarations).

For more far fetched senarios, that might be some module that can be
used as is for simple use cases and be integrated into some bigger API
by having a build script replacing '()' with '.call(someApiObject)'.

[toc] | [prev] | [next] | [standalone]


#22251

From"Robert Crandal" <noreply2me@yahoo.com>
Date2013-12-07 12:31 -0700
Message-ID<T_ydnZ1AqOvn6j7PnZ2dnUVZ5oOdnZ2d@giganews.com>
In reply to#22246
"Eric Bednarz" wrote:
>
> Although the combination of author and group you posted to is unlikely
> to yield productive answers, you should at least provide the book title
> and the chapter (ebooks make page numbers problematic).
>

It was "Secrets of the JavaScript Ninja", (c) 2013, by John Resig
and Bear Bibeault.  The code example is in Chapter 2, section 2.4.2,
page 24.

>
> In any case you should explain exactly what you shortened and/or
> modified.
>
>> /* Anonymous self-invoking function */
>> (function() {
>>   this.assert = function assert(a,b) { /* code here */  };
>>   this.test = function test(a, b) { /* code here */ };
>> })();
>>
>> /* Code for a testing environment or "test groups" */
>> window.onload = function() {
>>   test("Test one.", function() {
>>     assert(true, "Success!");
>>   });
>> }
>>

The only code that I omitted was the body of the assert()
and test() functions, and little bit of the code inside the
window.onload section, which is basically just:

       window.onload = function() {
            /* code here that calls test() and assert() */
       };

Basically, assert() and test() and defined and made publicly
accessible in the anonymous self-invoking function as seen
above.  These functions, test() and assert(), are then called
during window.onload.  That's the basic gist.

Robert


[toc] | [prev] | [next] | [standalone]


#22252

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-12-08 00:17 +0100
Message-ID<1963861.2MBlU7BgDz@PointedEars.de>
In reply to#22251
Robert Crandal wrote:

> "Eric Bednarz" wrote:
>> Although the combination of author and group you posted to is unlikely
>> to yield productive answers, you should at least provide the book title
>> and the chapter (ebooks make page numbers problematic).
> 
> It was "Secrets of the JavaScript Ninja", (c) 2013, by John Resig
> and Bear Bibeault.  The code example is in Chapter 2, section 2.4.2,
> page 24.

IIRC that or the previous book by Resig was a one that we discussed here 
already, and that started with stating utter nonsense like "HTML is an 
application of XML" or something similar stupid.  Rest assured that John 
Resig still does not have a clue about what he is doing – as evidenced by 
the inefficient bloated mess that still is jQuery – but he hides it well, 
and many people – especially the uninitiated – fall for appearances (as a 
poor substitute for logic).  Any “secrets” he might be able to reveal to you 
in there would have been discovered by other people, some posting in this 
newsgroup, years before he even started, or are not secrets in any meaning 
of the word at all.

In particular, the so-called Module Pattern (an “anonymous self-invoking 
function”) was popularized, if not invented, by Douglas Crockford, who used 
to post here (before he went down the path of madness that so far and AFAIK 
all JS book authors went).  However, AFAIK even Crockford was not so crazy 
as to suggest you should use “this” in there like that.

>> In any case you should explain exactly what you shortened and/or
>> modified.
>>
>>> /* Anonymous self-invoking function */
>>> (function() {
>>>   this.assert = function assert(a,b) { /* code here */  };
>>>   this.test = function test(a, b) { /* code here */ };
>>> })();
>>>
>>> /* Code for a testing environment or "test groups" */
>>> window.onload = function() {
>>>   test("Test one.", function() {
>>>     assert(true, "Success!");
>>>   });
>>> }
>>>
> 
> The only code that I omitted was the body of the assert()
> and test() functions, and little bit of the code inside the
> window.onload section, which is basically just:
> 
>        window.onload = function() {
>             /* code here that calls test() and assert() */
>        };
> 
> Basically, assert() and test() and defined and made publicly
> accessible in the anonymous self-invoking function as seen
> above.  These functions, test() and assert(), are then called
> during window.onload.  That's the basic gist.

This code, by your own account from a book published/edited in 2013, 
*breaks* in strict mode (with a TypeError in the first line of the function 
body, because “this” is the “undefined” value then), which was introduced 
with ECMAScript Edition 5 in December *2010*, and is recommended for 
production-quality code since then.  QED.

That the functions whose references are assigned to the properties of the 
ECMAScript global object (if not in strict mode) are named is particularly 
unnecessary and error-prone because of the known JScript bug.  Why would an 
“assert” function need a name, why would it need to call itself?  
Compatibility cannot be the reason for the naming because the outer function 
expression already is anonymous.

The proper way is either to explicitly call the function with a reference to 
the global object as the “this” value, or read “this” in global context into 
a variable and use that variable (and to avoid window.onload):

  (function (global) {
    global.assert = function () { … };
  }).call(this);

or

  (function (global) {
    global.assert = function () { … };
  }).call(null);

or

  (function (global) {
    global.assert = function () { … };
  }(this));

Since the latter suffices, and the former two are less compatible, the 
latter should be used.  On the other hand, if the private scope is not 
needed, the proper way is

  function assert ()
  {
    // …
  }

  function test ()
  {
    // …
  }

As for those two functions, however, it is better to have them *not* in the 
global namespace by default so that they do not interfere with the (test 
case) code that is using them.  See also 
<http://PointedEars.de/wsvn/JSX/trunk/test/test.js>.

-- 
PointedEars

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

[toc] | [prev] | [next] | [standalone]


#22253

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-12-08 01:08 +0100
Message-ID<5905423.NgFD1iC58s@PointedEars.de>
In reply to#22252
Thomas 'PointedEars' Lahn wrote:

> […]
> 
> The proper way is either to explicitly call the function with a reference
> to the global object as the “this” value, or read “this” in global context
> into a variable and use that variable (and to avoid window.onload):
> 
>   (function (global) {
>     global.assert = function () { … };
>   }).call(this);
> 
> or
> 
>   (function (global) {
>     global.assert = function () { … };
>   }).call(null);

JFTR:

  (function (global) {
    global.assert = function () { … };
  }).call(this);

or

  (function () {
    this.assert = function () { … };
  }).call(null);

or

  (function (global) {
    this.assert = function () { … };
  }).call(void 0);

> or
> 
>   (function (global) {
>     global.assert = function () { … };
>   }(this));
> 
> […]

-- 
PointedEars

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

[toc] | [prev] | [next] | [standalone]


#22260

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-12-08 19:41 +0100
Message-ID<2383855.kSGHYJAq6W@PointedEars.de>
In reply to#22253
Thomas 'Ingrid' Lahn wrote:

> Thomas 'PointedEars' Lahn wrote:
>> […]
>> 
>> The proper way is either to explicitly call the function with a reference
>> to the global object as the “this” value, or read “this” in global
>> context into a variable and use that variable (and to avoid
>> window.onload):
>> 
>>   (function (global) {
>>     global.assert = function () { … };
>>   }).call(this);

   (function (global) {
     global.assert = function () { … };
   }(this));
 
>> […]

-- 
PointedEars

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

[toc] | [prev] | [next] | [standalone]


#22263

Fromjaranmclarn@gmail.com
Date2013-12-08 12:21 -0800
Message-ID<8530fbc4-10d1-499d-a7d4-fc2082961a12@googlegroups.com>
In reply to#22253
Appologies for Typos... in last post ...I mean 'Thomas' not 'Lars'.

[toc] | [prev] | [next] | [standalone]


#22269

From"Robert Crandal" <noreply2me@yahoo.com>
Date2013-12-09 01:14 -0700
Message-ID<UKmdnWMybNSd4TjPnZ2dnUVZ5h6dnZ2d@giganews.com>
In reply to#22252
"Thomas 'PointedEars' Lahn" wrote:
>
>  Rest assured that John Resig still does not have a clue
> about what he is doing - as evidenced by the inefficient
> bloated mess that still is jQuery
>

Do you like other libraries besides jQuery?  I'm just curious.

>
> The proper way is either to explicitly call the function with a reference 
> to
> the global object as the "this" value, or read "this" in global context 
> into
> a variable and use that variable (and to avoid window.onload):
>

Okay, thanks for the help.

[toc] | [prev] | [next] | [standalone]


#22276

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-12-10 15:38 +0100
Message-ID<1948923.UqlRFHoYIj@PointedEars.de>
In reply to#22269
Robert Crandal wrote:

> "Thomas 'PointedEars' Lahn" wrote:
>>  Rest assured that John Resig still does not have a clue
>> about what he is doing - as evidenced by the inefficient
>> bloated mess that still is jQuery
> 
> Do you like other libraries besides jQuery?  I'm just curious.

1. How do you define “library”?

2. Why would it be relevant what I like?  Bad code is bad code
   whether I like it or not.
 
>> The proper way is either to explicitly call the function with a reference
>> to the global object as the "this" value, or read "this" in global
>> context into a variable and use that variable (and to avoid
>> window.onload):
> 
> Okay, thanks for the help.

You're welcome.

-- 
PointedEars

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

[toc] | [prev] | [next] | [standalone]


#22248

FromBjoern Hoehrmann <bjoern@hoehrmann.de>
Date2013-12-07 12:28 +0100
Message-ID<jd16a996va18gmvholm35f7lcpo8810ire@hive.bjoern.hoehrmann.de>
In reply to#22245
* Robert Crandal wrote in comp.lang.javascript:
>Subject: Anonymous self-invoking function

It sounded like this was about `arguments.callee` or with that being un-
popular http://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator
-- 
Björn Höhrmann · mailto:bjoern@hoehrmann.de · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/ 

[toc] | [prev] | [next] | [standalone]


#22249

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-12-07 12:57 +0100
Message-ID<1686096.R2xsbL7JtH@PointedEars.de>
In reply to#22248
Bjoern Hoehrmann wrote:

> * Robert Crandal wrote in comp.lang.javascript:
>> Subject: Anonymous self-invoking function
> 
> It sounded like this was about `arguments.callee` or with that being un-
> popular http://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator

In which parallel universe?

The question was about why an anonymous function was defined and called 
immediately when only the function body could have been executed.  While 
both “this” being “undefined” and “arguments.callee” have to do with strict 
mode (the first one applies then, and the second one is forbidden), the 
question has nothing to do with “arguments.callee”.

-- 
PointedEars

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

[toc] | [prev] | [next] | [standalone]


#22250

FromJoao Rodrigues <groups_jr-1@yahoo.com.br>
Date2013-12-07 16:51 -0200
Message-ID<l7vqn4$6r6$1@speranza.aioe.org>
In reply to#22245
On 06/12/2013 23:39, Robert Crandal wrote:
> I'm studying some code in one of John Resig's books.
> Here is a shortened/modified sample:
>
> /* Anonymous self-invoking function */
> (function() {
>    this.assert = function assert(a,b) { /* code here */  };
>    this.test = function test(a, b) { /* code here */ };
> })();
>
> /* Code for a testing environment or "test groups" */
> window.onload = function() {
>    test("Test one.", function() {
>      assert(true, "Success!");
>    });
> }
>
> So, it's my understanding that the properties "this.assert"
> and "this.test" defined above are publicly accessible functions.
> (Since the "var" keyword is missing this makes them
> properties of the global window object, right?).

Technically speaking, they are methods of the global object ("window" in 
web browsers), and this has nothing to do with the missing var keyword. 
And we could do the same as in

(function (global) {
   global.assert = function (a,b) { /* code here */  };
   global.test = function (a, b) { /* code here */ };
}(this));

But that is a bad idea since web browsers could implement such functions 
as native ones in future versions, or we could have conflicts with other 
libraries implementing such functions.

Also there is no need to name function expressions, unless the author 
intends to use recursion or use the debugging tools of modern browsers:

   this.assert = function assert(a,b) { /* code here */  };

We could simply use the anonymous function expression form:

   this.assert = function (a,b) { /* code here */  };

-- 
Joao Rodrigues

[toc] | [prev] | [next] | [standalone]


#22262

Fromjaranmclarn@gmail.com
Date2013-12-08 12:17 -0800
Message-ID<1a85f00c-d0b2-4e77-b7b5-37a2bd628dc5@googlegroups.com>
In reply to#22245
LOREMN

>>>So, it's my understanding that the properties "this.assert" 
and "this.test" defined above are publicly accessible functions.
    Yes.

>>>(Since the "var" keyword is missing this makes them properties of the global window object, right?).
     No. As I 'J.R.' mentioned The absence or presence of the 'var' keyword is on this occasion irrelevant. They are made properties on whatever object is serving as 'this' when the self-invoking function executes and that just happens in this case to the globally-scope-available 'window' object because of way JavaScript's internal algorithm comes into play when it creates an 'activation' object for the function its about to run i.e. (see jibbering.net ...closures)

++Have I got anything to add that hasn't already been mentioned? ++
  Resig shouldn't have coded it like this for at least two reasons.
  1) As Thomas 'PointedEars' Lahn stated (paraphrased in so many words Resig is being lazy)
  This is the code that is valid in ECMAScript 5 using 'use strict';


(function() {
 'use strict';
  
 /* Anonymous self-invoking function */  
 (function() { 
   this.assert = function assert(a,b) { /* code here */  }; 
   this.test = function test(a, b) { /* code here */ }; 
 }).call({}, this); 
 
 /* Code for a testing environment or "test groups" */ 
 window.onload = function() { 
   window.test("Test one.", function() { 
     window.assert(true, "Success!"); 
   }); 
 }; 

})(); /* Note this outer anonymous self-invoking function is  
         only there so I can shoehorn in the 'use strict'; JSHint.com
         moans if it is not there */

I don't know what's going on with the first two examples in Lars's code...(I just got an error and I think he's forgotten that with CALL() the first argument;s job is to be the object refenced by 'this' when the function invoked by call is run; the second and subsequent arrguments become the arguments passed into said function. So if in the function CALL is invoked upon has the parameter signature function(global) ... then the 2nd parameter (from my example 'this' i.e. 'call({}, this)' becomes mapped to the named local scope var called 'global' when this function executes...I've put in the '{}' as a placeholder. In Lars's example the 2nd argument in CALL's invocation is missing so 'global becomes undefined.
 2) Second reason I don't agree with J.Resig's coding. OK, the named function in the function expression does mean your debugger's call stack has a meaningful name to display should you have a breakpoint in the code ..i.e. this.assert = function assert(a,b) { debugger; /* code here */  };
...BUT... most Browser Dev Tools are clever enough to not just display 'Anoymous' function in their Call Stack output anyway (Chrome tells you that the function at the top of he callstack where execution has been paused is associated with the identifier 'assert').
  More subtley, J.Resig has overlooked the variable hoisting implications. I'm not going to go into this in too much detail suffice to say that Christian Johansen says in his book Test Driven JavaScript Development (page 84 sect 5.3.6) its not a good idea because its all too easy to introduce a code pattern that actually executes differently in different browsers..Don't believe me...? Try https://gist.github.com/jaranF/7863213

[toc] | [prev] | [next] | [standalone]


#22265

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-12-09 00:15 +0100
Message-ID<3978495.o0mb1hJGK2@PointedEars.de>
In reply to#22262
jaranmclarn@gmail.com wrote:
^^^^^^^^^^^^^^^^^^^^^
Who?

> LOREMN

I beg your pardon?

>   1) As Thomas 'PointedEars' Lahn stated (paraphrased in so many words
>   Resig is being lazy) This is the code that is valid in ECMAScript 5
>   using 'use strict';
> 
> 
> (function() {
>  'use strict';

It is not necessary to wrap the strict mode declaration in another function.  
It suffices that the script resource begins with the declaration.  (The 
Chromium script console has a known quirk there, though.)
   
>  /* Anonymous self-invoking function */
>  (function() {
>    this.assert = function assert(a,b) { /* code here */  };
>    this.test = function test(a, b) { /* code here */ };
>  }).call({}, this);

This would make (a reference to) a new Object instance the “this” value in 
the function when it is called.  The function would also be passed the 
global object as only argument which, since there is no formal parameter 
declared for it, would only be accessible using the “arguments” object.
  
>  /* Code for a testing environment or "test groups" */
>  window.onload = function() {
>    window.test("Test one.", function() {
>      window.assert(true, "Success!");
>    });
>  };
> 
> })(); /* Note this outer anonymous self-invoking function is
>          only there so I can shoehorn in the 'use strict'; JSHint.com
>          moans if it is not there */

JSHint.com is junk then.
 
> I don't know what's going on with the first two examples in [Thomas's]
> code...(I just got an error and I think he's forgotten that with CALL()

There is no “CALL”, the method name is “call” (case-sensitive).

> the first argument;s job is to be the object refenced by 'this' when the
> function invoked by call is run;

You have forgotten that as well above.  I have corrected myself twice before 
you posted your “correction”.

> the second and subsequent arrguments become the arguments passed into said
> function.

That is correct.  Which is why your code above is not equivalent.

> So if in the function CALL
> is invoked upon has the parameter signature function(global) ... then the
> 2nd parameter (from my example 'this' i.e. 'call({}, this)' becomes mapped
> to the named local scope var called 'global' when this function
> executes...I've put in the '{}' as a placeholder.

To what end?  You are not returning the reference to the newly created 
object, nor are you declaring a formal parameter or are accessing the global 
object in any other way.

> […]

Please either learn to post using Google Groups in a readable manner and
*in thread*, or use a newsreader like KNode, SeaMonkey or Thunderbird.  The 
latter is strongly recommended anyway because Google Groups is continuing to 
be buggy (i.e., ignoring both Internet standards and Usenet recommendations) 
and a source of spam.

-- 
PointedEars

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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web