Question

I previously run into the problems of data hiding under modularization in JavaScript. Please see the links below:

Module pattern- How to split the code for one module into different js files?

JavaScript - extract out function while keeping it private

To illustrate the problem, see the example below. My goal is to split my long js file into 2 files, but some functions need to access some private variables:

first.js:

(function(context) {
    var parentPrivate = 'parentPrivate';
})(window.myGlobalNamespace);

second.js:

(function(context) {
    this.childFunction = console.log('trying to access parent private field: ' + parentPriavte);
}(window.myGlobalNamespace.subNamspace);

Now this wouldn't work because child doesn't have access to parent. One solution is to make parentPrivate publicly visible, but that is unacceptable in my case.

Quoting @Louis who gave an answer for one of the previous questions:

"We can't have a field that's accessible by child but not to outside public (i.e. protected). Is there any way to achieve that?"

If you want modularization (i.e. you want the child to be coded separately from the parent), I do not believe this is possible in JavaScript. It would be possible to have child and parent operate in the same closure but then this would not be modular. This is true with or without RequireJS.

The problem is that the parent and the child are not inside the same closure. Therefore I'm thinking, does it make sense to create a library that puts files into the same closure?

Something like:

concatenator.putIntoOneClosure(["public/js/first.js", "public/js/second.js"]);

Of course we can take in more arguments to specify namespaces etc. Note that it is not the same functionality we get from RequireJS. RequireJS achieves modularization while this concatenator focuses on data hiding under the condition of modularization.

So does any of the above make sense? Or am I missing out some important points? Any thoughts are welcomed.

Was it helpful?

Solution

If you need things available in two separate files, then you can't have true privacy... however, something similar to this may work for you:

first.js:

(function(context) {
    var sharedProperties = {
      sharedProp1: "This is shared"
    };

   function alertSharedProp1() {
     alert (sharedProperties.sharedProp1)
   }


   window[context] = { 
     sharedProperties: sharedProperties,
     alertSharedProp1: alertSharedProp1
   };

})("myGlobalNamespace");

second.js:

(function(parent, context) {
    // CHANGED: `this` doesn't do what you think it does here.

    var childFunction = function() {
      console.log('trying to access parent private field: ' + window.myGlobalNamespace.sharedProperties.sharedProp1);
    };

    window[parent][context] = {
      childFunction: childFunction
    };

}("myGlobalNamespace", "subNamspace"));

window.myGlobalNamespace.subNamspace.childFunction();

Edit detailed answer based on comments

What I did was to set up a source file that looked like this:

master.js

(function() {    
   ##include: file1.js##
   ##include: file2.js##    
}());

Then I wrote a script (in windows scripting, in my case) that read in master.js and then read through line by line looking for the ##include: filename.js## lines. When it found such a line it read in the include file and just dumped it out.

My particular needs were special since I was writing a browser plugin that needed to work in three different browsers and had to be wrapped up separately, yet for my own sanity I wanted separate files to work with.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top