This question is about ES6 not about global variables.
When the new ES2015 export or export default were introduced. They were made so that you can import/get the same variables, values or items somewhere else using import. So I have a simple question. Why should we use export and import instead of just making a simple object of a class and getting items through it or just making static or global variables?
I know the fact that it can be used to make your code much cleaner and also to put the code easily into multiple files but let's just assume we have first.js and second.js and we have a variable called names in the first.js that we want to get in the second.js. Now you can either do that with import and export or by making an object in the second.js and accessing our variable by that object. So why is it better to use export and import?
export was introduced to be used alongside import (you need to explicitly declare what you need to later import), as part of the ES2015 module standard.
Before these standard modules were implemented, splitting up Javascript code into multiple files and not have all objects pollute the global object was only possible using sort short of non-standard module definition and/or module loaders like RequireJS. The simplest case was to wrap your code in Immediately Invoked Functions. ES6/2015 just standardize Javascipt modules.
Now you asked why not just have Javascript objects even in many files? The answer to that is namespacing
Actually - you make a good point.
namespace stuff is in C++. There are lots of people who think it is cool to have a namespace indicator in front of everything they use.
So, instead of saying { cout << my_string << endl; }, their whole program has { std::cout << my_string << std::endl; }.
Sometimes you see stuff like { disk::io::byte::bit::atom::neutron::quark::say_hi(2) }. And, the guy who wrote that thinks he's a super developer.
But, as they are purist, it more likely you will see { std::cout << myString << endl; } because camel case is so much more preferential than human readable strings.
Now, in node.js I am always doing something like const ClassFromMod = require('mod-with-class'). In the file, you have to say module.exports = ClassDeclaredInHere. I always do this, because really, is there any other way provided?
Or you can do this const {ClassFromMod} = require('mod-with-class').
Then you have to have, module.exports.ClassFromMod = ClassDeclaredInHere.
So, doing the same thing in the browser is sort of OK. But, now global contexts and local contexts are harder to work with - really. Just a little harder sharing things between modules when you have to. But, not to worry almost all of the time people partitions their modules just right. That's because they are people - in fact the sort of people who are more cautious than those in charge of nuclear reactors - because those people do some web programming. So, no Chernobyl when it comes to partitioning modules. Right?
Now, you can get your hands into a class def. And, the class is itself something of a namespace.
So, then why is there not a global registry of classes? Only that maybe different companies (individual developers) will use the same name for two remotely different classes. But, likely there would be some way around that.
One way might be to assign classes to uses (sort of name spacey). But, it might be more categorical. Like "engine" for something with a car feature, or "engine" for something that runs a script. Programming languages might have something like "talking about cars here". What would that be like?
start>> talking about cars <
let bval = engine.rev()
if ( bval ) {
<about scripts> engine.run("small program")
}
<<stop talking about car
That's an idea. Looking at it, I don' like it. It's sort of like "with" that lots of languages use.
So, with new strictures imposed on the programming environments, you get bugs and scope troubles that add to your long long long day. But, you should get that your question drawn from clear thinking is in some sense being steamrolled by a small group of people who can. And, you can take out the trash for them.
So, what about identifying objects by features and enabling sort of a flat namespace management? Could be driven by AI. Could have been done thirty years ago. But, now is now. But, the future exists for correcting the mistakes of the past.
Related
I understand the scoping rules of Node/JavaScript, and from, for example, Understanding Execution Context and Execution Stack in Javascript, I think I understand the principle of how Execution Contexts work: the question is can you actually get access to them?
From an answer to the 2015 question How can I get the execution context of a javascript function inside V8 engine (involving (ab)using (new Error()).stack), and the answer to the 2018 question How can we get the execution context of a function?, I suspect the answer is "no" but just in case things have changed: is it possible to access/modify the Execution Context of a Node module/function?
(I'm very aware this screams either XY Problem or a desire to abuse Node/JavaScript: hopefully the Background section below will provide more context, and – if there's a different way of achieving what I want – that will work as well.)
In a nutshell, I want to achieve something like:
sharedVar = 1 ;
anotherModule.someFunction() ;
console.log( sharedVar ) ; // Where 'sharedVar' has changed value
Having a function in a different module being able to change variables in its caller's scope at will seems the definition of "A Dangerous Thing™", so – if it's possible at all – I expect it would need to be more like:
sharedVar = 1 ;
anotherModule.hereIsMyExecutionContext( SOMETHING ) ;
anotherModule.someFunction() ;
console.log( sharedVar ) ; // Where 'sharedVar' has changed value
and anotherModule would be something like:
let otherExecutionContext ;
function hereIsMyExecutionContext( anExecutionContext ) {
otherExecutionContext = anExecutionContext ;
}
function someFunction() {
//do something else
otherExecutionContext.sharedVar = 42 ;
}
and the question becomes what (if anything) can I replace SOMETHING with?
Notes / Things That Don't Work (for me)
You shouldn't be trying to do this! I realize what I'm trying to achieve isn't "clean" code. The use-case is very specific, where brevity (particularly in the code whose value I want changing) is paramount. It is not "production" code where the danger of forgotten, unexpected side-effects matters.
Returning a new value from the function. In my real use-case, there would be several variables that I would like someFunction() to be able to alter. Having to do { var1, var2, ... varN } = anotherModule.someFunction() would be both inconvenient and distracting (while the function might change some of these variables' values, it is not the main purpose of the function).
Have the variables members of anotherModule. While using anotherModule.sharedVar would be the clean, encapsulated way of doing things, I'd really prefer not to have to use the module name every time: not only is it more typing, but it distracts from what the code that would be using these variables is really doing.
Use the global scope. If I wasn't using "use strict";, it would be possible to have sharedVar on the global object and freely accessible by both bits of code. As I am using strict-mode (and don't want to change that), I'd need to use global.sharedVar which has the same "cumbersomeness" as attaching it to anotherModule.
Use import. It looks like using import { sharedVar } from anotherModule allows "live" sharing of the variables I want between the two modules. However, by using import, the module using the shared variable has to be an ES Module (not a CommonJS Module), and cannot be loaded dynamically using require() (as I also need it to be). Loading it dynamically the ESM way (using import() as a function returning a promise) appears to work, but repeated loadings come from a cache. According to this answer to How to reimport module with ES6 import, there isn't a "clean" way of clearing that cache (cf. delete require.cache[] that works with CommonJS modules). If there is a clean way of invalidating a cached ESM loaded through import(), please feel free to add an answer to that question (and a comment here, please), although the current Node JS docs on ESMs don't mention one, so I'm not hopeful :-(
Background
In early December, a random question on SO alerted me to the Advent of Code website, where a different programming problem is revealed everyday, and I decided to have a go using Node. The first couple of problems I tackled using standalone JS files, at which point I realized that there was a lot of common code being copy-pasted between each file. In parallel with solving the puzzles, I decided to create a "framework" program to coordinate them, and to provide as much of the common code as possible. One goal in creating the framework was that the individual "solution" files should be as "lean" as possible: they should contain the absolute minimum code over that needed to solve the problem.
One of the features of the framework relevant to this question is that it reloads (currently using require()) the selected solution file each time, so that I can work on the solution without re-running the framework... this is why switching to import and ES Modules has drawbacks, as I cannot (cleanly) invalidate the cached solution module.
The other relevant feature is that the framework provides aoc.print(...) and aoc.trace(...) functions. These format and print their arguments: the first all the time; the second conditionally, depending on whether the solution is being run normally or in "trace" mode. The latter is little more than:
function trace( ... ) {
if( traceMode ) {
print( ... )
}
}
Each problem has two sets of inputs: an "example" input, for which expected answers are provided, and the "real" input (which tends to be larger and more involved). The framework would typically run the example input with tracing enabled (so I could check the "inner workings") and run the "real" input with tracing disabled (because it would produce too much output). For most problems, this was fine: the time "wasted" preparing the parameters for the call, and then making the call to aoc.trace() only to find there was nothing to do, was negligible. However, for one solution in particular (involving 10 million iterations), the difference was significant: nearly 30s when making the ignored trace; under a second if they calls were commented-out, or I "short-circuited" the trace-mode decision by using the following construct:
TRACE && aoc.print( ... )
where TRACE is set to true/false as appropriate. My "problem" is that TRACE doesn't track the trace mode in the framework: I have to set it manually. I could, of course, use aoc.traceMode && aoc.print( ... ), but as discussed above, this is more to type than I'd like and makes the solution's code more "cluttered" than I'd ideally want (I freely admit these are somewhat trivial reasons...)
One of the features of the framework relevant to this question is that it reloads the selected solution file each time
This is key. You should load not leave the loading, parsing and execution to require, where you cannot control it. Instead, load the file as text, do nefarious things to the code, then evaluate it.
The evaluation can be done with eval, new Function, the vm module, or by messing with the module system.
The nefarious things I was referring to would most easily be prefixing the code by some "implicit imports", whether you do that by require, import or just const TRACE = true;. But you can also do any other kind of preprocessing, such as macro replacements, where you might simply remove lines that contain trace(…);.
Looks like you're heading the wrong way. The Execution Context isn't meant to be accessible by the user code.
An option is to make a class and pass its instances around different modules for your purpose. JS objects exist in the heap and can be accessed anywhere as long as you have its reference, so you can control it at will.
I have to use this.state.<name> multiple times, how should I replace it with a simple variable name? Like we use global variables in other languages such as C, C++.
#Thomas yes, but there are a lot of functions in my code and even many items inside state for which i want shorter alias. So it is not ideal to do it with "const" in all functions. so by the word "globally", i meant how to declare those shorter alias only once ?
you can't. Javascript simply doesn't provide that feature.
JavaScript as a Language doesn't have the compile-step where these aliases would be filled in with the real commands.
There are preprocessors, like babel for wich you could write a plugin.
There are task-runner like gulp for wich you could write a script to build that aliasing syntax (although it's most likely not valid JS)
You can check out sweet.js maybe its functionalities already get you covered.
But maybe you'd consider learning JavaScript; realizing that JavaScript is not C and that you can't just transfer your coding style 1:1.
imo. the best Solution to get a bunch of shorter handles is Object destructuring. But this ain't aliases either; you need to understand what JS does here, and what the limits to this are.
Don't be too lazy to write a few more characters. Every modern JS IDE has an autocompletiton feature.
You can so something like this in render.
const { name } = this.state;
return(
<div>{name}</div>
)
Now you can use it just with name as many times you want in render as well you can do in methods.
It is not like creating alias but we can optimize code.
I am learning design pattern in JavaScript, and I'm going to use the module pattern. I'm puzzled with two things.
1 - If I would create a plugin, then I can use the module pattern, and have private and public methods/variables. But if I have a full JavaScript file, I don't need private and public methods, since one part of the program has nothing to do with another part. So what's the point of private and public methods?
2 - Since the JavaScript file is really long, should I have nested module's? How should I go about a full file of JavaScript?
JavaScript has moved on. ES6--which there is no real reason not to move up to, if you haven't already--has its own modules. So there is no need to "simulate" modules with old patterns. Example:
// Old style.
var myModule = function() {
var privateVar;
function getPrivateVar() { return privateVar; }
return {getPrivateVar: getPrivateVar};
}();
console.log(myModule.getPrivateVar());
// New style.
let privateVar;
function getPrivateVar() { return privateVar; }
export {privateVar};
// Using it
import {getPrivateVar} from './myModule';
console.log(getPrivateVar());
In the above, privateVar is by definition private to the module (file). There's no need to keep it private by wrapping it in an IIFE. Instead of handling the exports ourselves as properties of a single returned object, we use the ES6 export mechanism to export it explicitly.
(1)
When all Javascript files are loaded, all the scripts in all files are just like they are in one file. Script in one file can access (read, update, delete) global variables in other files. There are a lot of questions on this, you can easily search for those.
Of course, "one part of the program has nothing to do with another part", but in case you are in team with many members, each works on a part of the system (or in some cases, a file). Then, there is a chance that one person accidentally changes variables created by another person. Those kinds of error are quite easy to detect. But if you can modularize you script, you can avoid those kinds of error altogether.
(2)
You can go slow. While writing code to complete requirements, try to recognize the parts of code that can be separated to a modules (or even nested modules). Them put them into other files.
You should be creative and careful while doing so. The code might grow very fast and things get out of control very quickly.
Hello TypeScript/Angularists!
TL;DR
Can I pass angular dependencies to a TypeScript module/class, so that those dependencies DON'T become attributes of class objects - instead, they are available through scope function parameters?
I know the recommended way of declaring things in angular/typescript is to create a TS class inside a TS module and release it as an angular service, because:
it can't be a factory (see this)
it's good to have modules
a class (comparing to a plain function) might be used to check compile-time types in typescript
An example of such approach is below:
/// <reference path="../../project.d.ts" />
module project.core.services {
export class UiRoutes {
static $inject = ['$state'];
constructor(private $state: angular.ui.IStateService) {
}
public reloadCurrentView(): void {
this.$state.go(this.$state.current.name, this.$state.params, {
reload: true
});
}
}
}
project.core.CoreModule.service('UiRoutes', project.core.services.UiRoutes);
Anyway, there is one great problem with that approach and that is - I'm forced to pass all angular dependencies into class constructor to make them object attributes (available everywhere, not encapsulated - because if the object is accessible then all it's attributes are accessible).
As an alternative, there is Backbone.js + Require.js example:
define(['jquery', 'use!backbone','models/model'], function($, Backbone, Model){
View = Backbone.View.extend({
//...
});
return new View();
});
where, as you can see, jquery, backbone and some internal stuff is available, but it's not saved as an object attribute - it's available through scope. This is purely natural JavaScript way of doing things - passing things through scope function parameters. In this situation, you can encapsulate more things and your code becomes less verbose. And, mainly, it's good to have a choice rather than to be forced to follow the only right rule.
Now I know that backbone is different than angular and, moreover, DI is totally different than require.js, blah blah blah.
What I want is a an example (or just a design) that allow me to specify all angular dependencies and make them accessible for a TypeScript module/class but not to make them attributes of class objects. This is possible with pure AngularJS (without TypeScript) afterall, so it might be possible along with TypeScript.
PS I'll happily provide better description of the problem, if it's not clear (comments, please). Buit I'm not really interested in answers like "it's not what you want, but it works for me, try this" :) if the answer is "no, that's not possible", than I'd appreciate a proof and/or reasons why.
because if the object is accessible then all it's attributes are accessible
This may be true from a runtime perspective, but the runtime perspective is not the only one that matters. If you're using TypeScript and you mark the injected services as private, then no one is accessing these things unless they're being actively malicious. And odds are extremely good that your code is already not resilient to malicious actors inside its own runtime environment (trivially, someone who wanted to screw with your app could inject in any Angular service and overwrite its properties with their own).
So in that regard, the best thing to do is to not care about what things happen to be on a object somewhere versus in a closure somewhere.
Now I know that backbone is different than angular and, moreover, DI is totally different than require.js, blah blah blah.
To expand on "blah blah blah", a relevant difference here is that your requirejs module is effectively a singleton, whereas your Angular classes usually aren't (most of them are probably controllers).
We need to go back to the object vs closure difference to understand why that matters. If you're going to have closure privacy over your injected services (because compile-time privacy wasn't good enough for whatever reason), it follows that every instance of your object is going to need its own set of subclosures to be able to access those closed-over values.
Duplicating your function closures for every single instance of an object incurs a large performance penalty when there are many instances of the object. It's more allocations, more memory pressure, more time spent cleaning up things in the GC, more time spent marking or sweeping or refcounting in the GC, less locality of reference, less efficient JIT, and so on. This is why TypeScript and other languages don't give you ready-made footguns for making closure-based classes.
Now you're saying "But my service is a singleton!" and you're right. Singletons can be written as a closure like this:
module project.core.services {
export function UiRoutes($state: angular.ui.IStateService) {
function go() {
$state.go(/* etc*/);
}
function other() { }
function foo() { }
return {
go,
other,
foo
}
}
}
After doing some research on the subject, I've been experimenting a lot with patterns to organize my jQuery code (Rebecca Murphy did a presentation on this at the jQuery Conference for example).
Yesterday I checked the (revealing) module pattern. The outcome looks a bit reminiscent of the YUI syntax I think:
//global namespace MyNameSpace
if(typeof MNS=="undefined"||!MNS){var MNS={};}
//obfuscate module, just serving as a very simple example
MNS.obfuscate = function(){
//function to create an email address from obfuscated '#'
var email = function(){
$('span.email').each(function(){
var emailAddress = $(this).html().replace(' [ # ] ','#');
$(this).html('' + emailAddress + '');
});
};
return {
email: email
};
}();
//using the module when the dom's ready
jQuery(document).ready(function($){
MNS.obfuscate.email();
});
In the end I had several modules. Some naturally included "private members", which in this case means variables and/or functions which were only of importance for other functions within this module, and thus didn't end up in the return statement.
I thought having connected parts of my code (everything which has to do with the search for example) combined in a module makes sense, gives the whole thing structure.
But after writing this, I read an article by John (Resig), where he also writes about the performance of the module pattern:
"Instantiating a function with a bunch of prototype properties is very, very, fast. It completely blows the Module pattern, and similar, out of the water. Thus, if you have a frequently-accessed function (returning an object) that you want people to interact with, then it's to your advantage to have the object properties be in the prototype chain and instantiate it. Here it is, in code:
// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
return { /* Lots of properties */ };
}
(John mentions he is not against the module pattern "per se" though - just to let you know :)
Then I wasn't sure anymore if I was going into the right direction with my code. The thing is: I don't really need any private members, and I also don't think I need inheritance for the time being.
All I want for now is a readable/maintainable pattern. I guess this boils down to personal preference to a certain extend, but I don't wanna end up with readable code which has (rather serious) performance issues.
I'm no JavaScript expert and thus even less of an expert when it comes to performance testing. So first, I don't really know in how far the things John mentioned ("frequently-accessed function (returning an object) that you want people to interact with", lots of properties, etc.) apply to my code. The documents my code interacts with are not huge, with 100s or 1000s of elements. So maybe it's not an issue at all.
But one thing which came to my mind is that instead of just having
$('span.email').each(function(){
var emailAddress = $(this).html().replace(' [ # ] ','#');
$(this).html('' + emailAddress + '');
});
(inside the domready function), I create two "extra" functions, obfuscate and email, due to the use of the module pattern. The creation of additional functions costs some time. The question is: will it be measurable in my case?
I'm not sure if a closure is created in my example above (in an interesting post on the jQuery forum I read the following: "There is a philosophical debate on whether an inner function creates a closure if it doesn't reference anything on an outer function's variable object..."), but I did have closures in my real code. And even though I don't think I had any circular references in there, I don't know in how far this could lead to high(er) memory consumption/problems with garbage collection.
I'd really like to hear your input on this, and maybe see some examples of your code. Also, which tools do you prefer to get information on execution time, memory and CPU usage?
I also don't think I need inheritance for the time being
Indeed. This doesn't really apply to using modules as a namespace. It's about class instance analogues.
Objects you create by making every instance from a completely new {name: member} object are less efficient than objects you create using new Class with Class.prototype.name= member. In the prototype case the member value is shared, resulting in lighter-weight instances.
In your example MNS is a singleton, so there is no benefit to be had by sharing members through a prototype.
I'm not sure if a closure is created in my example above
Yes, it is. Even when no variables are defined in the outer function, there is still a LexicalEnvironment and scope object created for the outer function, with this and arguments bound in it. A clever JS engine might be able to optimise it away, since every inner function must hide this and arguments with their own copies, but I'm not sure that any of the current JS implementations actually do that.
The performance difference, in any case, should be undetectable, since you aren't putting anything significant in the arguments. For a simple module pattern I don't think there's any harm.
Also, which tools do you prefer to get information on execution time, memory and CPU usage?
The place to start is simply to execute the code 10000 times in a for-loop and see how much bigger new Date().getTime() has got, executed several times on as many different browsers as you can get hold of.
$(this).html().replace(' [ # ] ','#');
(What is this supposed to do? At the moment it will read the HTML of the span into a new String, replace only the first instance of [ # ] with #, and return a new String value. It won't change the existing content in the DOM.)
How much Javascript do you have? In my experience, on sites with lots of Javascript code on the pages, performance problems generally come from code that actually does things. Generally, problems stem from trying to do too many things, or trying to do some particular thing really badly. An example would be trying to do stuff like bind handlers to elements in table rows (big tables) instead of using something like "live".
My point is that things like how your modules or functions or whatever get organized is almost certainly not going to pose any sort of real performance issue on your pages. What is motivating you to go to all this trouble?