Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #22245 > unrolled thread
| Started by | "Robert Crandal" <noreply2me@yahoo.com> |
|---|---|
| First post | 2013-12-06 18:39 -0700 |
| Last post | 2013-12-09 00:15 +0100 |
| Articles | 14 — 6 participants |
Back to article view | Back to comp.lang.javascript
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
| From | "Robert Crandal" <noreply2me@yahoo.com> |
|---|---|
| Date | 2013-12-06 18:39 -0700 |
| Subject | Anonymous 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]
| From | Eric Bednarz <bednarz@fahr-zur-hoelle.org> |
|---|---|
| Date | 2013-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]
| From | "Robert Crandal" <noreply2me@yahoo.com> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | jaranmclarn@gmail.com |
|---|---|
| Date | 2013-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]
| From | "Robert Crandal" <noreply2me@yahoo.com> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | Bjoern Hoehrmann <bjoern@hoehrmann.de> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | Joao Rodrigues <groups_jr-1@yahoo.com.br> |
|---|---|
| Date | 2013-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]
| From | jaranmclarn@gmail.com |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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