How do you use class based OOP JavaScript in the browser? - javascript

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.

Related

return whole self invoking functions

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());

Reveal module pattern: Where to insert variables for module access

I'm learning reveal module pattern, and I'm trying to create a reusable function. (In my project, the function will make the page scroll. I don't think it's necessary to post the whole code here. I'm just putting the concept.)
The basic overview is, there's a function that will not return anything. There's no need for public variables. Here's the code. The questions are at the comments in the code:
JSFiddle
var MyModule = (function() {
// Is this the correct place to insert the
// variables that will be used throughout 'MyModule'?
var foo = 'foo',
foo2 = 'foo2',
param1 = null;
var MyModule = function(_param1) {
param1 = _param1;
logParam();
};
function init() {
foo = 'something';
}
function logParam() {
console.log(param1);
}
init();
return MyModule;
})();
var module = new MyModule('Some Paramater');
// Is this okay? Does it still follow reveal module pattern?
MyModule('Some Other Paramater');
// Or do I always have to do like this:
var module = new MyModule('Some Paramater');
The Module Reveal Pattern provides both private and public encapsulation.
Below an example with some explanatory comments.
More info about JavaScript pattern included Module Reveal Pattern can be found here
var myRevealingModule = (function () {
// below are private variables and functions that are not accessible outside the module this is possible thanks to a javascript closure
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
// below are public functions, they will be publicly available as they are referenced in the return statement below
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
console.log(myRevealingModule.greeting);// public
console.log(myRevealingModule.getName());// public
//console.log(myRevealingModule.privateFunction());// private, you cannot access it
Answering your comments:
// Is this okay? Does it still follow reveal module pattern?
MyModule('Some Other Paramater');
Yes, it's OK. If you want that your reveal module pattern "MyModule" must be selfclosing:
var MyModule = function(param1) {
var myPlublicFunction = function(){
}
return {
myPlublicFunction: myPlublicFunction
};
}(); //selfclosing
OR
// Or do I always have to do like this:
var module = new MyModule('Some Paramater');
If you want that, your reveal module pattern "MyModule" must be not selfclosing:
var MyModule = function(param1) {
var myPlublicFunction = function(){
}
return {
myPlublicFunction: myPlublicFunction
};
}; // not selfclosing
I hope it helps

JavaScript Singleton and IntelliJ Idea

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();

Difference between javascript constructors

I'm having a bit of confusion over which (if any) of these javascript initializes to use, as from what I can tel, they all do the same thing. Are there cases in which I should use one or he other? Mt project requires me to encapsulate several functions and namespaces in a single object so that we don't clutter te global scope with variable names, put I'm especially unclear as to the difference between +function(){}(); and (function())();
Any help would be greatly appreciated. Keep in mind the end goal is for all of our function to be encapsulated in a single namespace. IE MyCompany.function, MyCompany.Namepsace.Function ...
<script>
var Ford = {};
+function() {
Ford.start = function() {
console.log("Ford just started");
};
}();
Ford.start();
</script>
<script>
var Honda = {};
(function() {
Honda.start = function() {
console.log("Honda just srtarted");
};
})();
Honda.start();
</script>
<script>
var Toyota = function() {
return {
start: function() {
console.log("Toyota just strted");
}
};
}
var car = new Toyota();
car.start();
</script>
Javascript functions are only invoked as constructors when the new keyword is used. new creates a new object instance, inherits from the constructor's prototype, and makes the context of the this keyword the newly created object instance. So if you're not using the prototype to inherit properties or the keyword this to create new properties in the constructor--you don't really need to use a constructor.
I think what you're looking for is the module pattern which is implemented using immediately invoked functions. Both of your first two examples use immediately invoked functions. I believe the style (function(){}()); is preferred to +function(){}();. Both the surrounding () and the + cause the javascript parser to expect a function expression rather than a function declaration and this allows the trailing () to invoke the function. Besides being somewhat less readable + may also alter the return value of the function.
I think you want some variation on this (copied from link):
var MODULE = (function () {
var module = {};
var privateVariable = 1;
function privateMethod() {
// ...
}
module.moduleProperty = 1;
module.moduleMethod = function () {
// ...
};
return module;
}());
While all of that is valid JS, you're making assumptions that lead me to believe you may not understand how JS works. The first two example are not constructors in the usual sense at all...they're sort of module pattern, but not even. you could condense it to
var Honda = {};
Honda.start = function() { console.log("Honda just started"); }
and forget the self-executing function. What is shown above is similar to what you'd think of as a static function in other languages:
public class Honda {
public static void start() { Console.WriteLine("Honda Just Started"); }
}
If you wanted an instance function, you need to either attach to the prototype, or to the this keyword in the constructor:
Prototype:
var Honda = function() {}
Honda.prototype.start = function() { console.log("Honda just started"); }
This:
var Honda = function() {
this.start = function(){
console.log("Honda just started");
}
}
Your final example, with Toyota indicates you have a fundamental misunderstanding of how function constructors work. Your object has been discarded, and in return you get some object literal which could have been written:
var Toyota = {
start: function(){
console.log("Toyota just started");
}
}
What you (probably) intend is the "this" pattern I explained on the Honda example above:
var Toyota = function() {
this.start = function() {
console.log("Toyota just started");
}
}
Finally, when writing "namespaced" libraries of functions, the module pattern may be your best friend. This lets you maintain private state without the need for a formal constructor/prototypes, etc:
var MyCompany = {};
//car module
(function(ns){
var module,
_isStarted;
function start() { console.log('start'); _isStarted = true; }
function stop() { console.log('stop'); _isStarted = false; }
function isStarted() { return _isStarted; }
module = {
start: start,
stop: stop,
isStarted: isStarted
}
ns.CarModule = module;
}(MyCompany));
//use:
MyCompany.CarModule.start();
if(MyCompany.CarModule.isStarted()) { MyCompany.CarModule.stop(); }

JS turning a function into an object without using "return" in the function expression

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();

Categories

Resources