I'm having trouble with IntelliJ Idea's code completion and syntax checking and JavaScript.
I have the following (simplified) code for a Singleton object:
var MySingleton = new function() {
var self = this;
self.prop = "hello world";
self.printHello = function() {
console.log(self.prop);
};
};
MySingleton.printHello();
The problem is, that IntelliJ complains at the last line about Unresolved function or method printHello(). It also will not suggest printHello when autocompleting from MySingleton.. The code itself works fine though.
I guess I have to either annotate or rewrite my code in a different style. But how?
I am using factory to get Singeltons in Javascript.
var factory = function(){
this.singelton = null;
/**
* #return MySingleton
*/
function singelton(){
if(this.singelton==null){
this.singelton = new MySingelton();
}
return this.singleton;
}
}
var instance_of_my_singleton = factory.singelton();
It seems like the module pattern is close to what I want to do and is well supported by Idea's code indexing:
var MySingleton = (function () {
var self = this;
var prop = "hello world";
function printHello () {
console.log(self.prop);
};
// export public functions
return {
printHello: printHello
};
})();
MySingleton.printHello();
Related
How can I return the whole object of the self-inv-function without returning every functions manually?
I want to try with the following solution which should normally work, however, it does not work:
var publish = (function() {
var pub = {};
pub.hello = function() {
return "test"
};
return pub;
}());
now "pub" must be callable by subscribe:
var subsribe = (function(pub) {
function hello() {
return pub.hello();
};
}(publish));
I loaded both files in the browser (pub first).
However:
Debugger says: ReferenceError: pub not defined.
I think you want to write them like this:
var publish = (function() {
var pub = {};
pub.hello = function() {
return "test"
};
return pub;
})();
var subsribe = (function(pub) {
function hello() {
return pub.hello();
};
console.log(hello());
})(publish);
However, keeping a global reusable collections of functions can be accomplished in other ways, more elegantly maybe :) (separate file with export, singleton decorated with those methods)
You can't.
There's no mechanism in JS to get a list of variables in the current scope.
Even if you could, it probably wouldn't be a good idea as there would be no way to distinguish between public and private variables.
There is no such a mechanism but you can do something like this:
var publish = (function() {
const me = this;
let publicMethods = ['hello', 'bye'];
// private
function _hello() {
return "test";
};
function _bye() {
return "end test";
};
publicMethods.forEach((methodName) => {
let privateMethod = eval('_' + methodName);
Object.defineProperty(me, methodName, {
get: function() {
return privateMethod;
}
});
});
return this;
}());
console.log(publish.hello);
console.log(publish.bye);
console.log(publish.hello());
console.log(publish.bye());
I've been converting my procedural JS functions into a class and now I'd like to know when to instantiate it.
Here is my class:
MyProject = function() {};
MyProject.prototype.myProperty = "10";
MyProject.prototype.myMethod = function (value) {
// do something
}
Here is my HTML page:
<script src="javascriptfilesdirectory/MyProject.js"/>
<script>
function initialize() {
myProject = new MyProject();
}
</script>
<body onload="initialize()" >
My question is do I intialize it on page load and create a local variable as shown above or do I initialize it in the JS class file?
Here is my JS file:
MyProject = function() {};
MyProject.prototype.myProperty = "10";
MyProject.prototype.myMethod = function (value) {
// do something
}
myProject = new MyProject();
Also, I'm talking in general and in this case it's a singleton. I only want one copy of it in use.
If you really want it as a singleton, you can do it easier than that, something like:
var myProject = new (function() {
this.myProperty = "10";
this.myMethod = function(value) { }
})();
Your "class" is only defined long enough to assign it once, since you're never going to instantiate a second copy.
For a non-singleton, I tend to follow the pattern found on the TypeScript page:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var greeter = new Greeter("world");
Also, I'm talking in general and in this case it's a singleton. I only want one copy of it in use.
In that case, just directly create the object:
var myProject = {
myProperty: "10",
myMethod: function() { ... }
};
When and where you create the object doesn't matter, as long as you have access to it when and where you need it.
I'm trying to call a private function inside the revealing pattern. This is my code:
var module = (function(){
var privateMethod = function(val) {
console.log(val);
}
var publicMethod = function() {
var functionString = "privateMethod";
/** This what I tried
functionString.call('test');
window[module.privateMethod]('test');
*/
}
return {
init: publicMethod
}
})();
$(document).ready(function(){
module.init();
});
Someone could help me?
Thanks!
Make your private functions properties of an object?
var module = (function(){
var privateFuncs = {
privateMethod: function(val) {
console.log(val);
}
};
var publicMethod = function() {
var functionString = "privateMethod";
privateFuncs[functionString]('test');
};
return {
init: publicMethod
};
})();
Your other attempts both fail, for different reasons:
functionString.call('test') will never work because functionString refers to a string literal. It doesn't have a call method.
window[module.privateMethod]('test') won't work because firstly, module doesn't have a property privateMethod. It wouldn't be "private" if it did. That means you're attempting to invoke window[undefined], which is not a function.
i have seen in a framework (came across it once, and never again) where the developer defines a module like this:
core.module.define('module_name',function(){
//module tasks up here
this.init = function(){
//stuff done when module is initialized
}
});
since i never saw the framework again, i tried to build my own version of it and copying most of it's aspects - especially how the code looked like. i tried to do it, but i can't seem to call the module's init() because the callback is still a function and not an object. that's why i added return this
//my version
mycore.module.define('module_name',function(){
//module tasks up here
this.init = function(){
//stuff done when module is initialized
}
//i don't remember seeing this:
return this;
});
in mycore, i call the module this way (with the return this in the module definition):
var moduleDefinition = modules[moduleName].definition; //the callback
var module = moduleDefinition();
module.init();
how do i turn the callback function into an object but preserve the way it is defined (without the return this in the definition of the callback)?
you have to use:
var module = new moduleDefinition();
and then you're going to get an object.
Oh, and maybe you want to declare init as this:
this.init = function() {
Cheers.
How about something like this (I can only assume what mycore looks like):
mycore = {
module: {
definitions: {},
define: function(name, Module) {
this.definitions[name] = new Module();
this.definitions[name].init();
}
}
};
mycore.module.define('module_name', function () {
// module tasks up here
this.init = function () {
// init tasks here
console.log('init has been called');
};
});
I don't know what framework you're using or what requirements it places on you, but Javascript alone doesn't require a function to return anything, even a function that defines an object. For example:
function car(color) {
this.myColor = color;
this.getColor = function() {
return this.myColor;
}
//note: no return from this function
}
var redCar = new car('red');
var blueCar = new car('blue');
alert(redCar.getColor()); //alerts "red"
alert(blueCar.getColor()); //alerts "blue"
One more alternative http://jsfiddle.net/pWryb/
function module(core){this.core = core;}
function Core(){
this.module = new module(this);
}
Core.prototype.modules = {};
module.prototype.define = function(name, func){
this.core.modules[name] = new func();
this.core.modules[name].name = name;
this.core.modules[name].init();
// or
return this.core.modules[name];
}
var myCore = new Core();
var myModule = myCore.module.define('messageMaker', function(){
this.init = function(){
console.log("initializing " + this.name);
}
})
myModule.init();
Let's say I made use of the following module-kind pattern in JavaScript:
var myModule = (function () {
var Foo = function () { /* ... */ };
var Bar = function () {
this.foo = new Foo();
};
Bar.prototype.someMethod = function () {
this.foo.someMethod();
};
return {
'Bar': Bar
};
})();
Is it advisable and if yes - how can I expose Foo for unit testing? Is there some common technique or pattern for doing this?
I don't think you should really need to unit test the private members. As long as you have comprehensive tests on the public members, any errors within the private members will manifest themselves as errors on the public members. You can then use good ol' debugging to find out what the exact problem was.
Alternatively, if you have your tests run on a separate build to production, you could expose the enclosing object, and test against that. You'd need to remember to remove the reference to the enclosing object before deployment - or you could automate it somehow. Honestly though, I generally wouldn't bother removing it, unless you're packaging a library for public consumption.
var myModule = (function () {
var _this = this;
var Foo = function () { /* ... */ };
var Bar = function () {
this.foo = new Foo();
};
Bar.prototype.someMethod = function () {
this.foo.someMethod();
};
return {
'Bar': Bar,
'__private__': _this
};
})();
function test_foo(obj) {
var foo = obj.__private__.Foo;
assert(foo.prop, 10)
}
For an inhouse system, being able to access the private data/functions is usually a non-issue, if it is clearly understood that accessing private members should not be done. This is highlighted by providing a reference to the enclosing object with a name like __private__. (Can you tell I'm kinda into Python? ;) )