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


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

Exposing a module in the current scope

Started byAnton Shepelev <antonius@freeshell.de>
First post2021-03-18 19:21 +0300
Last post2021-04-13 18:49 +0300
Articles 4 on this page of 24 — 6 participants

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


Contents

  Exposing a module in the current scope Anton Shepelev <antonius@freeshell.de> - 2021-03-18 19:21 +0300
    Re: Exposing a module in the current scope Anton Shepelev <anton.txt@gmail.com> - 2021-03-18 23:57 +0300
      Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-18 18:45 -0700
        Re: Exposing a module in the current scope Anton Shepelev <anton.txt@g{oogle}mail.com> - 2021-03-19 18:11 +0300
          Re: Exposing a module in the current scope Anton Shepelev <anton.txt@g{oogle}mail.com> - 2021-03-19 19:08 +0300
            Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-19 10:51 -0700
              Re: Exposing a module in the current scope Anton Shepelev <anton.txt@gmail.com> - 2021-03-20 13:32 +0300
                Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-20 09:53 -0700
          Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-19 10:47 -0700
            Re: Exposing a module in the current scope Anton Shepelev <anton.txt@gmail.com> - 2021-03-20 13:51 +0300
              Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-20 09:59 -0700
                Re: Exposing a module in the current scope Anton Shepelev <anton.txt@g{oogle}mail.com> - 2021-03-24 20:43 +0300
            Re: Exposing a module in the current scope Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-03-22 21:14 +0100
              Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-22 16:00 -0700
                Re: Exposing a module in the current scope Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-03-23 01:11 +0100
                Re: Exposing a module in the current scope Anton Shepelev <anton.txt@gmail.com> - 2021-04-04 00:31 +0300
    Re: Exposing a module in the current scope "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2021-03-18 11:30 -0700
    Re: Exposing a module in the current scope Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-03-22 21:05 +0100
    Re: Exposing a module in the current scope Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-03-23 01:00 +0100
      Re: Exposing a module in the current scope Anton Shepelev <anton.txt@g{oogle}mail.com> - 2021-03-23 20:06 +0300
        Re: Exposing a module in the current scope Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2021-03-25 20:04 +0100
          Re: Exposing a module in the current scope John G Harris <niam@jghnorth.org.uk.invalid> - 2021-03-26 08:32 +0000
          Re: Exposing a module in the current scope John G Harris <niam@jghnorth.org.uk.invalid> - 2021-03-26 08:48 +0000
    Re: Exposing a module in the current scope Anton Shepelev <anton.txt@g{oogle}mail.com> - 2021-04-13 18:49 +0300

Page 2 of 2 — ← Prev page 1 [2]


#39767

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2021-03-25 20:04 +0100
Message-ID<1925707.oMNUckLgyt@PointedEars.de>
In reply to#39748
Anton Shepelev wrote:

> Thomas 'PointedEars' Lahn:
>> But an alternative standard-compliant and backwards-
>> compatible way is what has been called an IEFE
>> ("immediately executed function expression") or a simiilar
>> term:
>>
>>    $.import("anton_test/util.xsjslib","util"); // import module
>>    $.anton_test.util.log("Log from library."); // invoke a function
>>
>>    (function (log) {
>>      /* ... */
>>    }($.anton_test.util.log));
> 
> You invoke an immediate function with the log function as the parameter.

No, I am passing a *reference* to the Function instance as the _argument_
of the anonymous function, therefore that becomes the _value_ of the formal 
parameter “log”, and the evaluation result of the _identifier_ “log” in the 
function execution context.

> What for?

So that you can write log(…) inside that function, which is what
*you* wished to do.  But actually, AISB, the safe way would be to pass 
$.anton_test.util.log.bind($.anton_test.util).  See below.

> -- to create a scope with it
> acessible by the name of `log'?

You have a misconception as to what the word “scope” means, and what a scope 
is in ECMAScript implementations.

>> The same caveat applies above as for
>>
>>    const log = $.anton_test.util.log;
>>
>> which is why typically one writes
>>
>>    (function (util) {
>>      util.log("Log from library.");
>>    }($.anton_test.util));
> 
> Now you invoke an immediate function with the module as the
> parameter, and that function invokes util.log() internally.
> In what way is it better than the previous version?

Then there is no risk of getting a wrong “this” value inside log(), so no 
need to use Function.prototype.bind() to use the correct value, and 
potentially reduce efficiency.

> Still missing your point, I looked IEFE up on Wikipedia, but their
> example of IOEFE benefits seems flawed from the start:
> 
>    var v, getValue;
>    v = 1;
>    getValue = function () { return v; };
>    v = 2;
> 
>    getValue(); // 2
> 
> is rewritten as:
> 
>    var v, getValue;
>    v = 1;
>    function f(x) {
>        return function () { return x; };
>    };
>    getValue = f(v);
>    v = 2;
> 
>    getValue();  // 1

This is NOT an IEFE.

> Why on earth would anyone want to write a function that
> accesses/captures a global variable,

It does not.  The point of this example, which has absolutely nothing to do 
with what I discussed, is to "capture" the *value* of the variable at the 
time that the returned function was *created*.  Regardless of the current 
value of the variable “v”, the created function, which is referred to by 
“getValue”, will always return 1.

Look up “closure”.

> […] If the log function does not access global variables,
> 
>    const log = $.anton_test.util.log;
> 
> should be perfectly safe, right?

Wrong, AISB.  Run this:

  var answer = 23;

  const my = {
    answer: 42,
    log: function () { console.log(this.answer); }
  };

  /* Non-strict mode */
  (function () {
    my.log();

    const log = my.log;
    log();

    const log2 = my.log.bind(my);
    log2();
  }());

  /* Strict mode */
  (function () {
    'use strict';

    my.log();

    const log = my.log;
    log();

    const log2 = my.log.bind(my);
    log2();
  }());

N.B.: Using “const” or “let” instead of “var” avoids the output of “23”
in both modes as variables declared in the new way do NOT become properties 
of the global object when declared in the global execution context; but 
“undefined” is put out when we still wanted to see “42” instead.
 
>> BTW, I would expect the module loader of such a module
>> system to return, if successful, a reference to the module
>> object such that Ц if synchronous execution cannot be
>> avoided -
> 
> Why avoid it?

It blocks execution of other code due to the single-threadedness of the 
ECMAScript execution process; in a Web browser that also means that it 
blocks the current tab, all other tabs in the same window, or the entire Web 
browser.

Therefore, synchronous XHR, for example, is deprecated in at least Chromium 
since several versions, and support for it might be removed in the future.

> […]

Your overconfident statements are indicative, as they are unfortunately 
typical, for a "JavaScript" beginner (who derives their "knowledge" only
from the unfortunately many bad books and articles on the topic).

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

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


#39769

FromJohn G Harris <niam@jghnorth.org.uk.invalid>
Date2021-03-26 08:32 +0000
Message-ID<uu6r5gtom3eamsijm36650fkjbkrjhfi33@4ax.com>
In reply to#39767
On Thu, 25 Mar 2021 20:04:19 +0100, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:

>Anton Shepelev wrote:

  <snip>
>> You invoke an immediate function with the log function as the parameter.
>
>No, I am passing a *reference* to the Function instance
  <snip>

Thomas is expressing his personal preference for how to describe
what the program will do. Your preference, Anton, is perfectly 
legitimate. In fact it is simpler, and simpler while still giving
the right result is better.

Remember, though, that if the variable b holds an object and you do
  c = b;
then b and c now hold the *same* object. That's why you can use b to
alter a property of the object and then use c to see the change.

  John

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


#39771

FromJohn G Harris <niam@jghnorth.org.uk.invalid>
Date2021-03-26 08:48 +0000
Message-ID<bs7r5ghs48addfetieuq089kjv2kaqrl2v@4ax.com>
In reply to#39767
On Thu, 25 Mar 2021 20:04:19 +0100, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:

>Anton Shepelev wrote:

  <snip>
>> You invoke an immediate function with the log function as the parameter.
>
>No, I am passing a 
  ...
> as the _argument_
  <snip>

Thomas is too superior to explain the difference between a parameter
and an argument. If you have
  function f(x){ return x+1; }  // Function definition
	f(3);                         // Function call
then x is the parameter, a name used in saying what the function must
do, and 3 is the argument, a value substituted for x when executing
the function. "Parameter" and "argument" are used with these meanings
in both maths and computing.

  John

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


#39919

FromAnton Shepelev <anton.txt@g{oogle}mail.com>
Date2021-04-13 18:49 +0300
Message-ID<20210413184923.86b25e151c333324c99c3e94@g{oogle}mail.com>
In reply to#39693
Thomas 'PointedEars' Lahn:

> While there is at least one fancy way to do this for
> several and selected properties only (which a custom
> module system might provide), the simple code
>
>    const util = $.anton_test.util;
>
> (or
>
>    var util = $.anton_test.util;
>
> to be backwards-compatible), is literally the best that
> you can do, in general.
>
> Note that
>
>    const log = $.anton_test.util.log;
>
> is NOT equivalent because `$.anton_test.util.log()' may
> use УthisФ to refer to `$.anton_test.util' which will
> refer to the global object, or (in strict mode) be the
> УundefinedФ value, if you then call Уlog()Ф.  The
> equivalent variant would be
>
>    const log = $.anton_test.util.log.bind($.anton_test.util);
>
> but when emulated for backwards compatibility (and maybe
> even when Function.prototype.bind() is available
> natively), this comes at the price of reduced runtime
> efficiency when it is is called.  So just to be able to
> write `log' instead of `util.log' does not appear to be
> worth it.

Thank you for the explanation, Thomas. Now I understand why
most of JavaScript code imports modules rather than their
separate members. My own code, however, is not going to rely
on `this', so I can import individual functions from modules
that I write.

You rightly indicate name collisions as another potential
problem, but programmers have successfully dealt with them
in less clumsy ways than prepending each imported function
with a module identifier.

-- 
()  ascii ribbon campaign - against html e-mail
/\  http://preview.tinyurl.com/qcy6mjc [archived]

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

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


csiph-web