Is there a problem with my implementation of the module pattern? - javascript

I've written the following as an implementation of the module pattern:
let myClass = function (publicName, privateName)
{
this.publicVar = publicName;
let privateVar = privateName;
this.publicMethod = function ()
{
return this.publicVar;
}
this.getPublic = function ()
{
return this.publicMethod();
}
this.setPublic = function (newPublicName)
{
this.publicVar = newPublicName;
}
this.getPrivate = function ()
{
return privateVar;
}
this.setPrivate = function (newPrivateName)
{
privateMethod(newPrivateName);
}
let privateMethod = function (newPrivateName)
{
privateVar = newPrivateName;
}
return this;
}
let a = new myClass('public A', 'private A');
let b = new myClass('public B', 'private B');
// A
console.log(a.publicVar);
console.log(a.publicMethod());
console.log(a.getPrivate());
a.setPrivate('private A-2');
console.log(a.getPrivate());
console.log(a.getPublic());
a.setPublic('public A-2');
console.log(a.getPublic());
// B
console.log(b.publicVar);
console.log(b.publicMethod());
console.log(b.getPrivate());
b.setPrivate('private B-2');
console.log(b.getPrivate());
console.log(b.getPublic());
b.setPublic('public B-2');
console.log(b.getPublic());
It differs from examples I can generally find on the web though, as it doesn't use an IIFE, and doesn't use a constructor as such...
Is there a problem with what I've done?
I can't see anything wrong with it personally... It seems to encapsulate the methods and variables as it should.
NOTE: I also realise that a lot of the methods are unnecessary, I just wanted to test a few things to see if I could break 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());

Execute "static" method of a parent of a constructor accessed from a constructor array in Javascript

Phew, even the question was hard to write. Here's the problem: I have a "game", more like a random simulator, which needs to choose a random action from an array of actions, like this one:
actions = [ Action1, Action2, Action3 ]
I have actions written as classes inheriting from the Action parent class:
function Action() {
this.targets = [];
this.used = [];
this.execute = function(player) {
doStuff();
return whatever;
};
}
//btw the below I've seen in a JS OOP tutorial but it doesn't work and I have to implement init() in every child action
Action.init = function(player) {
var a = new this.constructor();
return a.execute(player);
};
Action.checkRequirements = function() {
return true;
};
Action1.prototype = new Action();
Action1.prototype.constructor = Action1;
function Action1 {
this.execute = function(player) {
doStuff();
return whatever;
}
}
Action1.init = function(player) {
var a = new Action1();
return a.execute(player);
}
So what I'm doing to execute an action and get its results is var foo = actions.getRandomVal().init(); (getRandomVal is a simple custom script that returns a random value from the array) It works well, creates the object instance which properly inherits all properties and methods, executes the exec() method and returns its results... but now I have a checkRequirements() method which I want to implement in like 10% of the 100+ actions I wish to do, and I want it to simply be inherited from the Action class so that when it is not implemented in the child class it simply returns true and I don't have an idea how. If I do var a = actions.getRandomVal(); and then a.checkRequirements(); it throws an exception that a.checkRequirements is not a function.
PS: this is a relatively small non-profit project for a (large) group of friends, I don't need it to work in every browser, it needs to work in Chrome and I can just tell them to use Chrome for it.
Since you only need to work with Chrome, I'd suggest to use ES6 class syntax which does all the inheritance properly, without the chance to mess up. This includes your Action1 constructor to inherit properties ("static class members") from the Action constructor as you'd expect.
class Action {
constructor() {
this.targets = [];
this.used = [];
}
execute(player) {
doStuff();
return whatever;
}
static init(player) {
var a = new this(); // no .constructor
return a.execute(player);
}
static checkRequirements() {
return true;
}
}
class Action1 {
execute(player) {
doOtherStuff();
return whateverelse;
}
}
It looks to me like you're calling checkRequirements() on an instance:
a.checkRequirements();
But it's implemented statically:
Action.checkRequirements = function() {
return true;
};
You probably want to bind this function to the prototype, so change the code above to this:
Action.prototype.checkRequirements = function() {
return true;
};
Then when you want to override this in a derived type, like Action1, you can do this:
Action1.prototype.checkRequirements = function () {
return (whatever);
}
As per comments, my guess is you want something like this...
// base Action type providing basic implementation
// Wrapped in an IIFE to prevent global scope pollution
// All functions are prototype bound to allow prototypical inheritance.
var Action = (function () {
function Action() {
this.targets = [];
this.used = [];
};
Action.prototype.doStuff = function () {
return;
}
Action.prototype.execute = function (player) {
this.doStuff();
return "whatever";
}
Action.prototype.checkRequirements = function () {
return "foo";
}
return Action;
})();
var Action1 = (function () {
Action1.prototype = new Action();
Action1.prototype.constructor = Action1;
function Action1() {
}
Action1.prototype.checkRequirements = function () {
// Super call
return Action.prototype.checkRequirements.call(this);
}
return Action1;
})();
var Action2 = (function () {
Action2.prototype = new Action();
Action2.prototype.constructor = Action2;
function Action2() {
}
Action2.prototype.checkRequirements = function () {
return "bar";
}
return Action2;
})();
// Set up array.
var array = [Action1, Action2];
// Create instances (this is where you would pick at random)
var a1 = new array[0]();
var a2 = new array[1]();
// var aofn = new array[rnd]();
// Tests
alert(a1.checkRequirements()); // Should "foo" because it called super (Action).
alert(a2.checkRequirements()); // Should "bar" because it's overridden.
Check it out on TypeScript Playground

inherit javascript function prototype outside it closure

I am using JavaScript prototype chaining technique to chain functions as shown below:
var foo = (function () {
function fn(arg) {
if (!(this instanceof fn)) {
return new fn(arg);
}
this.arg = arg;
return this;
}
var func = function (element) {
return fn(element);
};
fn.prototype = {
bar: function () {
return this;
}
}
func.functions = fn;
return func;
}());
I would like to know how to access fn.prototype so I can add more functionality to the foo prototype outside its closure.
If I just simply do as follows, it won't work:
foo.prototype.baz = function () {
alert(this.arg);
}
foo("hello").baz();
However if fn assigned to the foo (func.functions = fn;) as it shown in the foo private closure I can do as follow and it will works:
foo.functions.prototype.baz = function () {
alert(this.arg);
}
foo("hello").baz();
Is there any other way to achieve this?
I think you are un-necessarily overcomplicating this. You can chain by simply doing this:
const foobar = function(){return this} // Initialize a new Object
const foo = text => {
const me = new foobar()
me.text = text
me.bar = a => (alert(me.text+": "+a), me)
return me
}
foo('A').bar('Test').bar('Test chained')
// Update the foobar class with baz
foobar.prototype.baz = function() {alert('BAZ worked!');return this}
foo('B').bar('1').baz().bar('2')
Note: Click Run code snippet to see the output
That's it!
Edit:
You can also do this with ES6 classes like:
class foobar {
constructor(text) {
this.text = text;
}
bar(a) {alert(this.text+": "+a);return this}
}
const foo = text => new foobar(text)
foo('A').bar('Test').bar('Test chained')
// Update the foobar class with baz
foobar.prototype.baz = function() {alert('BAZ worked!');return this}
foo('B').bar('1').baz().bar('2')

javascript design pattern: how to create sub-module and access parent module private vars and functions

I have the following:
mod.a = (function() {
var myPrivateVar = 'a';
function myPrivateFct() {
//do something I will need in my sub-module (mod.a.b)
}
return {
//some public functions
}
})();
mod.a.b = (function() {
// some local vars and functions
return {
mySubModuleFct:function() {
// here I want to call mod.a.myPrivateFct();
}
})();
I want to create a sub-module and call a private function from my parent module mod.a. How can I do this while following the best practices of the module pattern?
A coworker showed me how to do it. It's actually very elegant.
mod.a = (function() {
var myPrivateVar = 'a';
function myPrivateFct() {
//do something I will need in my sub-module (mod.a.b)
}
return {
b: {
bPublicMethod:function() {
myPrivateFct(); // this will work!
}
}
//some public functions
}
})();
//call like this
mod.a.b.bPublicMethod(); // will call a.myPrivateFct();
I would suggest using John Resig's Simple Inheritance code for more object-oriented approach to javascript:
http://ejohn.org/blog/simple-javascript-inheritance/
It allows you to write this:
var Person = Class.extend({
init: function(isDancing){
this.dancing = isDancing;
}
});
var Ninja = Person.extend({
init: function(){
this._super( false );
}
});
var p = new Person(true);
p.dancing; // => true
var n = new Ninja();
n.dancing; // => false

Javascript: best Singleton pattern [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Simplest/Cleanest way to implement singleton in JavaScript?
I'm using this pattern for singletons, in the example the singleton is PlanetEarth:
var NAMESPACE = function () {
var privateFunction1 = function () {
privateFunction2();
};
var privateFunction2 = function () {
alert('I\'m private!');
};
var Constructors = {};
Constructors.PlanetEarth = function () {
privateFunction1();
privateFunction2();
};
Constructors.PlanetEarth.prototype = {
someMethod: function () {
if (console && console.log) {
console.log('some method');
}
}
};
Constructors.Person = function (name, address) {
this.name = name;
this.address = address;
};
Constructors.Person.prototype = {
walk: function () {
alert('STOMP!');
}
};
return {
Person: Constructors.Person, // there can be many
PlanetEarth: new Constructors.PlanetEarth() // there can only be one!
};
}();
Since PlanetEarth's constructor remains private, there can only be one.
Now, something tells me that this self-cooked thing isn't the best one can do, mostly because I don't have an academic education and I tend to solve problems in stupid ways. What would you propose as a better alternative my method, where better is defined as stylistically better and/or more powerful?
(1) UPDATE 2019: ES7 Version
class Singleton {
static instance;
constructor() {
if (instance) {
return instance;
}
this.instance = this;
}
foo() {
// ...
}
}
console.log(new Singleton() === new Singleton());
(2) ES6 Version
class Singleton {
constructor() {
const instance = this.constructor.instance;
if (instance) {
return instance;
}
this.constructor.instance = this;
}
foo() {
// ...
}
}
console.log(new Singleton() === new Singleton());
Best solution found:
http://code.google.com/p/jslibs/wiki/JavascriptTips#Singleton_pattern
function MySingletonClass () {
if (arguments.callee._singletonInstance) {
return arguments.callee._singletonInstance;
}
arguments.callee._singletonInstance = this;
this.Foo = function () {
// ...
};
}
var a = new MySingletonClass();
var b = MySingletonClass();
console.log( a === b ); // prints: true
For those who want the strict version:
(function (global) {
"use strict";
var MySingletonClass = function () {
if (MySingletonClass.prototype._singletonInstance) {
return MySingletonClass.prototype._singletonInstance;
}
MySingletonClass.prototype._singletonInstance = this;
this.Foo = function() {
// ...
};
};
var a = new MySingletonClass();
var b = MySingletonClass();
global.result = a === b;
} (window));
console.log(result);
Why use a constructor and prototyping for a single object?
The above is equivalent to:
var earth= {
someMethod: function () {
if (console && console.log)
console.log('some method');
}
};
privateFunction1();
privateFunction2();
return {
Person: Constructors.Person,
PlanetEarth: earth
};
Extending the above post by Tom, if you need a class type declaration and access the singleton instance using a variable, the code below might be of help. I like this notation as the code is little self guiding.
function SingletonClass(){
if ( arguments.callee.instance )
return arguments.callee.instance;
arguments.callee.instance = this;
}
SingletonClass.getInstance = function() {
var singletonClass = new SingletonClass();
return singletonClass;
};
To access the singleton, you would
var singleTon = SingletonClass.getInstance();

Categories

Resources