I found this brilliant post about namespace pollution, which notes that - beside of conflicting name definitions - using global variables may have ...
For further actions, you may consider blocking this person and/or reporting abuse
Hy Eckehard,
Look at this book online from Addy Osmani
Especialy the Revealing Pattern : RP
Regards
Thank you for the hints.
I think we can achieve the same result using classes, which has the advantage that you can use setters and getters.
I just wanted to avoid the module name on every function call. Maybe in Javascript, the only option are named imports.
The entire idea behind the revealing module pattern is to keep the "private" parts truly "private" inside a function closure created via an intermediately invoked function expression (IIFE). JavaScript always had function closures.
OOP with Functions in JavaScript
Private class fields are only part of the Class field declarations for JavaScript and private methods are part of the Private methods and getter/setters for JavaScript classes TC39 proposals which are currently at Stage 3 - which means they may become part of ES2023 if they go to Stage 4 before then.
Babel right now includes @babel/plugin-proposal-class-prope... and @babel/plugin-proposal-private-met... by default in
@babel/preset-env
Can I Use: JavaScript classes: Private class fields
Can I Use: JavaScript classes: Private class methods
MDN: Private Class Features
In the example given the object returned includes the
getName()
accessor and thesetName()
mutator. But perhaps you were referring to the getter and setter object property syntax:It just works!
Hy Eckehard
In a module you cant import whatever variables from another one, and use them without any prefix.
TodoListTutor
Feel free to correct :-)
Regards
PS : Have you considered turning DML UI Elment in customeElements ?
TodoListCE
No, we had a focus on long term compatibility (expect IE), CE had a limited support some years ago.
I try to keep modules as small as possible. But maybe somebody could write a wrapper as a separate module? On the other hand, what's the advantage?
For the CE , it was in fact to illustrate,how easy it was to create one.
You can create a lib containing only DML-CE like Shoelace for CSS
But if IE is a concerned, you can look at a article I post WE
which allows create CE without any polyfill that works even in IE.
Regards
People get easily overwhelmed with his contributions so it's best to always pass along:
I know, unfortunately.
Thank you peerenders :-)
Inside a module you can import only what you want from antother one, like this
Yes, I know. We should use ES-modules instead of scripts. But - they come at a price and I did not find a satisfying solution for me right now. Please let me explain:
First, we should have a look, how modules are organized in other languages like C++ or Delphi. Generally, you need to import any module explicitly into your source. Each module has a header, that defines precisely, what is exported, very similar to what you do in Javascript. Modules often are based on other Modules, so they may export a very large number of symbols that are accessible in your source then.
Generally you try to keep your interfaces narrow, but complex systems may export 10.000 symbols that - in principle - are acessible in your source.
BUT: Behind the scene, we have an intelligent linker that checks, which parts or the source was used in your code and just extracts, what is needed. In large hierarchies you may have hundreds of name clashes, which is absolutely no problem as these languages have a different way to deal with a clash.
In Javascript, such a situation would crash the whole system. So, what are the drawbacks:
a) Import/export is only supported on the top level, you cannot define a more fine grained access control. Compiled languages usually know different levels of visibility (privat, public, published, ...) outside and inside of classes. For me, the benefit though is a bit limited.
b) Putting every used symbol in an import list is kind of boring. Think of a large module with hundreds of exports. This is a job a computer could do far better than me, and I think, we shouldn't do the work for the computers, it should be the other way around.
c) Maybe you are a bit lazy and use the whole export list as import. This will pollute your namespace with lot´s of unused symbols, which is just the topic of this post.
So, I´m just wondering if there are other solutions that have less drawbacks. Maybe we could have some kind of "intelligent loader", that just loads the parts of a module when it´s needed first? Or at least a automatic import list generator? Or there is a different way to organize the code?
In the example above, DML exports lot´s of handy definitions like this:
This is just for convenience, but adding an "export" to every definition will blow up the code and does not really solve the namespace issues.
I would really appreciate to find a better solution for this topic. (Please don´t tell me I´m a bad programmer... As I mentioned already: There are different ways to catch a tiger.)
I will never say to anyone he is a bad programmer,
again, I am very happy to have discovered your library :-)
Your problem could be submited to Andrea Giammarchi from WebReflections.
I am pretty sure he could respond about the possibility of a 'lazy loading'
Regards
1) It may help to organize things into fewer values
2) These type of values are typically managed by an entirely different tool, e.g. Sass (also gorko).
There is a solution do avoid named input (the lazy way), which is not the final word, but maybe an interesting starting point:
In DML.js, we set the export:
Now we import our library as dml and make it accessible in the global scope
I know this is a bad solution for many reasons. But it might be a starting point:
The solution above defines all symbols as global variables, which we wanted to avoid. I just did not find a way to define scoped (e.g. local) variables that way. If we could manage to create scoped variables, this has many advantages:
So, my question is: Does anybody know a way to create local variables or const dynamically in Javascript?
The final solution could be something like this:
Perhaps using 'eval' ?
But as you know it's not recommended.
1.) It is not uncommon for style guides to discourage the use of wildcard imports even when the language supports it. Example:
Wildcard imports should not be used
Also keep in mind that in C/C++
include
occurs at compile-time so there is no runtime cost to dumping a boatload of unused names into the code. In JavaScriptimport
happens at run time so potential for "more work" comes with the potential for undesirable run time consequences.Other than that, for example, Google's style guide with regards to imports.
2.) In your example it looks like you are trying to export functions that are only capable of creating a single type of HTML element
Prior art:
For a while React also had react-dom-factories:
However support was dropped as JSX is the accepted standard among React developers.
Other helper examples: hyperscript-helpers, react-hyperscript.
3.)
Basically strict mode which is the default in ES2015 modules makes that impossible.
However for the time being one can still pull a stunt like this:
I like any kind of dirty tricks, but 'eval' is really nasty. As this may cause serious security issues I would not try to use it. But I´m sure there will be a solution without.
Andrea Giammarchi reminded me, that rollup.js might be perfect. That´s indeed a smart solution!
Great, Andrea is an awesome guy
In fact I have published your TodoList using rollup and it's tree shaking feature :-)
MDN: Function:
Also functions created with
Function
don't default to strict mode so it is possible to use the with statement which has been not welcome for the last decade.The suggested alternative leads us back to
It would let you work with smaller modules which are less prone to having a large number of exports that are then stitched together at build time - so wildcard imports would be much less problematic. In my judgement rollup.js is probably the most sane bundler solution at this time (even when esbuild is faster; Parcel is way too magical for my taste).
Are the extra
* as
characters really worth fretting about?No, but this forces to use the libary name on any function or variable of any library you use. The C++-solution is far more handy, only to use a qualifier where necessary.
Douglas Crockford, JavaScript - The Good Parts, 2008; p.2:
2008 is long ago. Javascript has made a good progress over the last years and gained a lot of strength (and speed). I still think the designers made some strange decisions, but overall I´m not unhappy. The lack of strong typing makes less trouble than I expected and gives you some flexibility, that other languages miss.
I think it is absolutely OK to compare Javascript with other languages. Lot´s of things HAVE been changed already, but for some things we need to find tricks and solutions to make better use of it. That´s the reason we are talking about.
The quote is timeless because people constantly try to find their language inside of JavaScript and only end up perpetually creating grief for themselves. The message of the book was to let go of any preconceived notion from other programming languages (and paradigms) and to simply deal with JavaScript on its own terms. That advice is as valid today as it was back then.
It's natural for people to stick to the familiar but when it comes to programming languages outside of the OOP, imperative bubble (C, C++, C#, Java, Python etc.) it's time get a fresh start.
JavaScript uses a familiar C-style syntax but Brendan Eich had Scheme on the brain when he designed it - and it shows to this day (Yes, JavaScript is a Lisp).
With TypeScript Microsoft (being Microsoft) tried to gloss over that fact:
… but as they were actually trying to type (most) JavaScript code they had to go far beyond
class
andinterface
.In fact the introduction of
class
in ES2015 was controversial as it was seen as a means to make JavaScript more palatable to programmers coming from mainstream OOP languages - especially give that even in 1994 GoF recommended (p.20):Also JavaScript was already truly object-oriented given that code could always construct objects even without facilities such as classes or even constructor functions i.e .it was never class-based.
And as the MDN states:
In JavaScript objects can be augmented - so an object's class-membership isn't permanent for life. And in ES5 factory functions were in common use for creating objects.
These days classes have become an important part of "the platform" - given that the original Web API was already largely object-based, classes became the mechanism by which natively implemented facilities are now extended with JavaScript.
But to some degree this has more to do with "the browser as an environment that can be automated with JavaScript" rather than "JavaScript the Programming Language" - even from the very beginning people have conflated (the "messy") DOM API (a part of the browser) with JavaScript (the programming language).
Yes, V8 is phenomenally fast but JavaScript is still an interpreted language and none of the "progress" has substantially changed the underlying character of JavaScript. JavaScript simply can't take advantage of the tricks that most compiled languages can.
Whenever you run into a "strange decision" have a look at ES Discuss and TC39/proposal to see what went into making that decision - you may be surprised at the wide range of perspectives that were considered - not that it makes the decision any less weird in retrospect.
On the server-side that makes sense because you can switch when you can see the balance tipping. I still regularly 🤦♂️ when I discover that some organization chose to use JavaScript on the server when there are clearly other, better options. The whole universal, isomorphic argument seems a bit self-serving - though in some cases for small teams it can make sense (Marko).
But when it comes to the browser there is no real alternative other than perhaps transpiling to JavaScript - so that conversation is really going nowhere.
WebAssembly:
If you really wanted to you could use C++ Compiling a New C/C++ Module to WebAssembly (I'd rather go with Rust) - but is that always an effective solution?
And languages that require separate multi-megabyte run times aren't going to succeed outside of niche applications - JavaScript doesn't have to ship a separate runtime and Web APIs are all designed with JavaScript in mind.
On top of everything else, by necessity software running in the browser is subject to very different design constraints than software running somewhere in a cloud server data centre. Given The Mobile Performance Inequality Gap, 2021 the cavalier attitude of creating a product by indiscriminately aggregating many packages from npm may be tolerable for some server side work but is absolutely the wrong direction for client side products.
"We need this to run to on a low powered embedded system - no, wait we're not allowed to ship binary code - we can only send JavaScript and the deployed engine will already be claiming most of the system's resources."
… is probably a more appropriate perspective for approaching client-side product design.
Perhaps rather than stating something like:
ask something like
The XY Problem
Sorry, but your comments are a bit off topic. At least, now I know why some people are called tech-evangelists - they cannot stop praying. You do not even know what task I want so solve, so how do you know, you have the right tools?
Please, stay on topic. There your help is much appreciated.
What about imports inside a module? This pollutes the namespace of the module, but not the global namespace:
html
<- module A <- libA
<- module B <- libB
I assume that dynamic import would also help to get short loading times in some cases.
This was a questions about the scope of the global namespace inside a module. I assume, something like window[myVariable] = "NewValue" is not possible in a module?!?
var
andfunction
declarations in inline JavaScript that pollute the global object (typically prevented with an IIFE). This doesn't happen intype="module"
or ECMAScript modules - those names are "module global" but do not create properties on the global object.const
andlet
are block scoped so they don't affect the global object.window['myVariable'] = 'NewValue';
is possible.