I am writing a javascript framework using the module pattern, which looks like this:
var EF = (function(doc) {
// Main public object
var e = {
version: "1.0.0",
doc: doc,
log: true
};
// Private methods
var method1 = function(el) {
<some code>
}
var method2 = function(el) {
<some code>
}
var method3 = function(el) {
<some code>
}
// PUBLIC METHODS ASSIGNMENT
e.method1 = method1;
e.method2 = method2;
e.method3 = method3;
return e;
}(document));
Now I decided that I should move some methods to the separate file.
During development I then would load two files one by one in the HTML file, while for deployment I would merge them in a single file.
What is the correct way move part of the methods to a separate files keeping the structure of the code that I use?
I've seen the following suggestion in one of the answers on stackoverflow:
var MODULE = (function (my) {
var privateToThisFile = "something";
// add capabilities...
my.publicProperty = "something";
return my;
}(MODULE || {}));
It looks almost like what I need, but it shows private methods for the file and for the module. But I need private methods for the module and pubic methods for the module.
What suggestions would you have?
I am not sure what exactly you want, but I guess you want to access the private function via module object. In essence it's public pointer to a private property.
Let me know further if I can help you. A problem example with a jsFiddle would be great.
var myRevealingModule = function () {
var privateCounter = 0;
function privateFunction() {
privateCounter++;
}
function publicFunction() {
publicIncrement();
}
function publicIncrement() {
privateFunction();
}
function publicGetCount(){
return privateCounter;
}
// Reveal public pointers to
// private functions and properties
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetCount
};
}();
myRevealingModule.start();
Related
I just started using Closure Compiler, and I'm seeing some inconsistent behavior regarding obfuscation of public object methods.
I'm using grunt-closure-compiler - here's my grunt config:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
'closure-compiler': {
app: {
closurePath: 'closure-compiler',
js: 'src/app.js',
jsOutputFile: 'js/app.min.js',
maxBuffer: 500,
options: {
compilation_level: 'ADVANCED_OPTIMIZATIONS',
language_in: 'ECMASCRIPT5_STRICT',
formatting: 'PRETTY_PRINT'
}
}
}
});
grunt.loadNpmTasks('grunt-closure-compiler');
};
And here's app.js the file I want to obfuscate:
(function() {
/**
* #constructor
*/
function MyClass() {
var map = {};
this.put = function(name, val) {
map[name] = val;
};
this.get = function(name) {
return map[name];
};
}
var mapper = new MyClass();
mapper.put("first", 123);
alert(mapper.get("first"));
})();
(function() {
/**
* #constructor
*/
function Foo() {
var private_member_1 = 'bla';
this.someMethod = function(param1, param2) {
// do some stuff
console.log('abc');
return private_member_1;
};
// etc...
}
var foo = new Foo();
var value = foo.someMethod();
console.log(value + value);
})();
And this is the output after running grunt closure-compiler:app
'use strict';(function() {
var a = new function() {
var a = {};
this.put = function(b, c) {
a[b] = c;
};
this.get = function(b) {
return a[b];
};
};
a.put("first", 123);
alert(a.get("first"));
})();
(function() {
var a = (new function() {
this.a = function() {
console.log("abc");
return "bla";
};
}).a();
console.log(a + a);
})();
Notice that in the first closure the methods put and get were not obfuscated, while in the second closure the method someMethod was obfuscated.
Why does this happen? And how can I cause all public methods in all of my classes (like put and get) to be obfuscated as well?
Please note -
I am willing to use a different tool other than Closure Compiler to achieve this.
I want to use this with TypeScript, i.e. obfuscate the compiled TypeScript code, this is why I have many public methods.
Some specific methods are API methods that should not be obfuscated. So I need a way to tell the obfuscator which methods to skip.
Update
As of the 20150315 release of Closure-compiler, the type based optimizations are enabled by default.
This is actually covered in the project FAQ.
The option you want is use_types_for_optimization. This will enable property renaming even if a property of the same name is defined on an unrelated object.
The comprehensive list of properties which can only be renamed with this flag is huge: any property name defined on any object in an extern file.
I figured it out - get and put are considered reserved words, and closure compiler ignores them on purpose.
I ran across a list of these reserved words earlier, but I can't find it now... would appreciate if someone posts a link to the complete list.
Having a project where I have speed coded up some core functionality I would like to split it up into modules. My struggle now is how to combine prototypes from one to the next. My idea is something like this:
(function (window) {
/* Code for base module with core functions. */
function CORE () {
}
window.CORE = CORE; /* I use different naming in real code ... */
})(window);
(function (CORE) {
/* Code for module with extending functionality. */
function MODULE1 () {
}
CORE.MODULE1 = MODULE1;
})(window.CORE);
I use an approach for creation as something like:
(function (window) {
var Core = function (options) {
return new Core.prototype.init(options);
}
Core.prototype = {
init : function (options) {
this.a = options.a;
return this;
}
}
Core.prototype.init.prototype = Core.prototype;
Core.prototype.init.prototype.fun1 = function () { }
Core.prototype.init.prototype.fun2 = function () { }
...
window.Core = Core; /* Optionally = Core.init */
})(window);
And then a module like:
(function (Core) {
var Module1 = Core.Module1 = function (options) {
return new Module1.prototype.build(options);
}
Module1.prototype = {
build : function (options) {
this.a = options.a;
return this;
}
}
Module1.prototype.build.prototype = Module1.prototype;
Module1.prototype.build.prototype.fun1 = function () { }
Module1.prototype.build.prototype.fun2 = function () { }
...
Core.Module1 = Module1;
Core.Module1_XO = Module1.prototype.build;
})(window.Core);
Now a print of toString() of Core, Core.Module1 and Core.Module1_XO all yield their respective code. But there is no binding as in:
If I say:
var obj = Core({...}); , OK.
obj.Module1({...}), Fail. Object #<Object> has no method Module1
new obj.Module1_XO({...}), Fail. undefined is not a function
Core.Module1({...}), OK, but looses prototypes from Core.
new Core.Module1_XO({...}), OK, but looses prototypes from Core.
...
One way that seem to work is by updating Core by a bind function as in:
var obj = Core({...});
var mod1 = Core.Module1({...}, obj); <-- pass obj
// In Module1 constructor:
build : function (options, ref) {
this.a = options.a;
ref.bind("Module1", this);
}
// And In Core:
Core.prototype.bind(which, what) {
this[which] = what;
}
Question is how I can update Core with Module without this hack. Why doesn't Core become updated by:
window.Core.Module1 = Module1;
Is it hidden from Core?
I have also tried to bind in outer scope of module as in:
(function (Core) {
/* ... code ... for Mudule1 */
Core.bind("Module1", Module1);
}(window.Core);
But this fails as well. Core does not get updated with methods from Module.
Here is a scramble of a fiddle I have messed with, (Note that the printed text is in reverse (prepended) not appended such as newest on top.). It is not the most tidy code, and It is in midts of edits. (I try new approaches frequently.)
What you're doing right now is problematic for several reasons:
You're adding a module to the constructor (type) and not the objects.
Global state here - everyone gets one Module1.
My suggestion would be using a generic version of the builder pattern (or even a mediator).
Here is what it might look like.
Core = (function Core(){
var modules = [];
return {
setModule : function(name,value){
modules.push({name:name,value:value});
},
build : function(options){
this.a = options.a;
// now let's add all modules
modules.forEach(function(module){
this[module.name] = new module.value();
});
}
};
});
Usage would be something like:
var app = new Core.build({a:"foo"});
app.a;//"foo"
If you want to add a module it'd be something like
function Module1(){
this.name = "Zimbalabim";
}
Core.setModule("Module1",Module1);
var app = new Core.build({a:"Bar"});
app.Module1.name;//"Zimbalabim"
app.a;//"Bar"
Or course, a more generic architecture would allow creating different apps with different architectures (with dependency injection containers probably) but let's not go that far yet :)
I have read a lot of articles about how to create modules in node.js, and you can use module.exports to expose module internals to the file which includes it.. awesome!
How does this work the other way around? I'll use the following as an example :-)
USER.JS
function User() {
this.property = 'value';
this.doSomething = function() {
var getStuff = mainFileFunction();
// do something with getStuff
}
module.exports = User;
MAIN.JS
var myArray = [];
myArray.push('something');
myArray.push('something else');
mainFileFunction() {
for(thing in myArray) {
return myArray[thing];
}
}
var u = new user();
log(u.property); <--- THIS IS EXPOSED, COOL!
u.doSomething(); <--- This will throw an error because mainFileFunction is not defined in user.js :-(
If I were to move mainFileFunction to the user file, then it still wouldn't work because the myArray array wouldn't be defined... and if I were to move that over too, I wouldn't be able to use it in other functions in main (which I want to) :-)
I'm sorry if I'm missing something really obvious here... What I want is to expose the parts of my choosing from modules I include (module.export works for that) but I also want to expose everything from the main file to all the includes..
or just expose everything to everything? is that totally messy and horrible??
Just to explain what I am trying to do here... I want to have classes defined in separate files, but I want to instantiate a bunch of them as objects in the main file and store them in arrays.. I want the objects to contain methods which can access arrays of the other object types.
Thanks guys! :-)
You can use globals, or have a proper circular dependency (requireing both files), however - this is usually a bad habit which can lead to maintainability problems in the future.
Instead, you can use dependency injection and inject doSomething into your module.
This basically gives you the following for free:
You can test User with a simple mock implementation of doSomething later and verify the correctness of your code
The dependencies of a user are explicit and not implicit, which makes it obvious what a user needs.
I'll provide two implementations, one using constructor dependency injection and one with a module wide setting.
USER.JS
function User(dependentFunction) {
this.property = 'value';
this.doSomething = function() {
var getStuff = dependentFunction();
// do something with getStuff
}
}
module.exports = User;
MAIN.JS
...
var u = new User(mainFileFunction);
u.doSomething(); // this will now work, using mainFileFunction
What happens here is fairly simple, and we know what's going on.
This can also be a module wide setting
USER.JS
function User(depFunc) {
this.property = 'value';
this.doSomething = function() {
var getStuff = depFunc();
// do something with getStuff
}
}
function UserFactory(depFunc){
return function(){
return new User(depFunc);
}
}
module.exports = UserFactory;
MAIN.JS
var getUser = UserFactory(mainFileFunction);
var u = getUser(); // will return a new user with the right function
+1 to Benjamin answer for dependency injection.
I would like to add another way to inject objects in your modules by passing the dependency in the require like require('./module.js')(dependentFunction);
//MAIN.js
var db = function() {
this.rows = [];
this.insert = function(name) {
this.rows.push(name);
console.log('Db: Inserting user with name ' + name);
}
this.getAll = function(){
return this.rows;
}
}
var fakeDb = new db();
var user = require('./user.js')(fakeDb);
user.add('Jhon');
user.add('Rose');
user.list();
and
//users.js
module.exports = function(db) {
return {
add: function(name) {
db.insert(name);
},
list: function() {
var users = db.getAll();
var i = users.length;
console.log('listing users\n-------');
while(i--) {
console.log(users[i]);
}
}
}
}
You should pass mainFileFunction as a parameter to the constructor of user.
USER.JS
function User(mainFileFunction) {
this.property = 'value';
this.doSomething = function() {
var getStuff = mainFileFunction();
// do something with getStuff
}
module.exports = User;
In your main.js use the following
var u = new user(mainFileFunction);
How about moving mainFileFunction to user.js, and have the function accept an array as an argument:
mainFileFunction(array) {
for(thing in array) {
return array[thing];
}
}
And then when you call it from main.js, pass the function your array:
u.doSomething(myArray);
How can I create a function that can't be called from outside?
var obj = {
function1: function(){
alert("function1");
},
function2: function(){
alert("function2...");
obj.function1();
}
};
// so how to make this function unaccessible
obj.function1();
// and you could only call this function
obj.function2();
You may want to consider using the Yahoo Module Pattern. This is a singleton pattern, and the methods are not really static, but it may be what you are looking for:
var obj = (function () {
//"private" variables:
var myPrivateVar = "I can be accessed only from within obj.";
//"private" method:
var myPrivateMethod = function () {
console.log("I can be accessed only from within obj");
};
return {
myPublicVar: "I'm accessible as obj.myPublicVar",
myPublicMethod: function () {
console.log("I'm accessible as obj.myPublicMethod");
//Within obj, I can access "private" vars and methods:
console.log(myPrivateVar);
console.log(myPrivateMethod());
}
};
})();
You define your private members where myPrivateVar and myPrivateMethod are defined, and your public members where myPublicVar and myPublicMethod are defined.
You can simply access the public methods and properties as follows:
obj.myPublicMethod(); // Works
obj.myPublicVar; // Works
obj.myPrivateMethod(); // Doesn't work - private
obj.myPrivateVar; // Doesn't work - private
The simple answer is that you can't do both. You can create "private" methods or "static" methods, but you can't create Private static functions as in other languages.
The way you can emulate privacy is closure:
function f() {
function inner(){}
return {
publicFn: function() {},
publicFn2: function() {}
}
}
Here because of closure, the inner function will be created every time you call f, and the public functions can acces this inner function, but for the outside world inner will be hidden.
The way you create static methods of an object is simple:
function f() {}
f.staticVar = 5;
f.staticFn = function() {};
// or
f.prototype.staticFn = function() {};
Here the function object f will only have one staticFn which has access to static variables, but nothing from the instances.
Please note that the prototype version will be inherited while the first one won't.
So you either make a private method that is not accessing anything from the instances, or you make a static method which you doesn't try to access from the outside.
You can use a closure, something along the lines of....
var construct = function() {
var obj = {};
var method1 = function() {
alert("method1");
}
obj.method2 = function() {
alert("method2...");
method1();
}
return obj;
}
obj = construct();
Then:
obj.method2 is accessible, but obj.method1 doesn't exist for public usage. It can be only accessed using member functions of the class.
Objects can be produced by constructors, which are functions which initialize objects. Constructors provide the features that classes provide in other languages, including static variables and methods.
Read all about it at http://www.crockford.com/javascript/private.html
You can do it like this:
var obj = new function() {
var method1 = function() { // private }
this.method2 = function() { // public }
}
obj.method1(); // not possible
obj.method2(); // possible
Note that I also use an anonymous constructor. This is sort of analogous to the Singleton pattern.
Maybe you want a proxy object containing only the public methods, e.g.
var obj = (function() {
var obj = {
method1: function(){
alert("method1");
},
method2: function(){
alert("method2...");
obj.method1();
}
}
return {
method2: function() { return obj.method2.apply(obj, arguments) }
}
})()
// you could only call this function
obj.method2();
// this function inaccessible
obj.method1();
I don't see the point of private methods in javascript. If you don't want people calling a method then don't advertise it. Private methods also make debugging just that bit harder too.
This is how it really should be done.
var MyClass = new(function() {
var privateStaticVariable = '';
function privateStaticMethod() {
}
function construct() {
var self = this;
this.publicMethod = function() {};
function privateMethod() {
//maybe lest use our private static method
privateStaticMethod();
}
}
construct.publicStaticVariable = '';
construct.publicStaticMethod = function() {};
return construct;
})();
Now lets use it:
var myClass = new MyClass();.....
MyClass.publicStaticMethod();
MyClass.publicStaticVariable = 'sfdsdf';
myClass.publicMethod();
.....
Use class. Though some of the features are still not shipped as it’s at Stage 3.
const instance = new (class Alpha {
static #private_static_method() {
console.info("I am private and static.");
}
static public_static_method() {
Alpha.#private_static_method();
console.info("I am public and static.");
}
#private_nonstatic_method() {
console.info("I am private and non-static.");
}
public_nonstatic_method() {
this.#private_nonstatic_method();
console.info("I am public and non-static.");
}
});
instance.constructor.public_static_method();
// instance.constructor.#private_static_method(); // impossible
instance.public_nonstatic_method();
// instance.#private_nonstatic_method(); // impossible
Is there a way to get all methods (private, privileged, or public) of a javascript object from within? Here's the sample object:
var Test = function() {
// private methods
function testOne() {}
function testTwo() {}
function testThree() {}
// public methods
function getMethods() {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
}
return { getMethods : getMethods }
}();
// should return ['testOne', 'testTwo', 'testThree', 'getMethods']
Test.getMethods();
The current issue is the code in getMethods(), the simplified example will return just the public methods, but not to private ones.
edit: my test code may (or may not) be overcomplicating what i'm hoping to get at. given the following:
function myFunction() {
var test1 = 1;
var test2 = 2;
var test3 = 3;
}
is there a way to find out what variables exist in myFunction() from within myFunction(). the pseudo-code would look like this:
function myFunction() {
var test1 = 1;
var test2 = 2;
var test3 = 3;
alert(current.properties); // would be nice to get ['test1', 'test2', 'test3']
}
The technical reason why those methods are hidden is twofold.
First, when you execute a method on the Test object, "this" will be the untyped object returned at the end of the anonymous function that contains the public methods per the Module Pattern.
Second, the methods testOne, testTwo, and testThree aren't attached to a specific object, and exist only in the context of the anonymous function. You could attach the methods to an internal object and then expose them through a public method, but it wouldn't be quite as clean as the original pattern and it won't help if you're getting this code from a third party.
The result would look something like this:
var Test = function() {
var private = {
testOne : function () {},
testTwo : function () {},
testThree : function () {}
};
function getMethods() {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
for (i in private) {
alert(i); // private methods
}
}
return { getMethods : getMethods }
}();
// will return ['getMethods', 'testOne', 'testTwo', 'testThree']
Test.getMethods();
edit:
Unfortunately, no. The set of local variables aren't accessible via a single, automatic keyword.
If you remove the "var" keyword they would be attached to the global context (usually the window object), but that's the only behavior that I know of that is similar to what you're describing. There would be a lot of other properties and methods on that object if you did that, though.
From http://netjs.codeplex.com/SourceControl/changeset/view/91169#1773642
//Reflection
~function (extern) {
var Reflection = this.Reflection = (function () { return Reflection; });
Reflection.prototype = Reflection;
Reflection.constructor = Reflection;
Reflection.getArguments = function (func) {
var symbols = func.toString(),
start, end, register;
start = symbols.indexOf('function');
if (start !== 0 && start !== 1) return undefined;
start = symbols.indexOf('(', start);
end = symbols.indexOf(')', start);
var args = [];
symbols.substr(start + 1, end - start - 1).split(',').forEach(function (argument) {
args.push(argument);
});
return args;
};
extern.Reflection = extern.reflection = Reflection;
Function.prototype.getArguments = function () { return Reflection.getArguments(this); }
Function.prototype.getExpectedReturnType = function () { /*ToDo*/ }
} (this);
Javascript doesn't really have the notion of private anything. Because of that, javascript doesn't have a reflection API as such. The technique you're using doesn't so much make them private as render them inaccessible; they're hidden, not private. I think you could manage something by putting those methods somewhere manually.
Part of the issue with your test code is that Test is the object created by your return statement: "{ getMethods : getMethods }" It has no testOne, testTwo, or testThree methods; instead, those are only available within the same namespace as the original getMethods function.
With a little change to the way the function is defined you can achieve what you want. Wrap the actual implementation of the function in an object literal it would then look like this:
(function() {
var obj = {
// private methods
testOne: function () {},
testTwo : function () {},
testThree: function () {},
// public methods
getMethods : function () {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
}
};
return { getMethods : function(){return obj.getMethods();} }
})();
you can use var that = this; trick:
var Test = function() {
var that = this;
function testOne() {}
function testTwo() {}
function testThree() {}
function getMethods() {
for (i in that) {
alert(i);
}
}
return { getMethods : getMethods }
}();
If you call getMethods() like that, isn't it static? Surely you'd need to properly init the class for this to work as expected?
var t = new Test();
t.getMethods();
If that doesn't work, please take a look at the JS Serializer. I used it a while back for some debug and I think it worked for private vars.