I'm creating an abstraction above a couple very similar, but different interfaces and can't decide on the best way to structure my code to keep is as DRY as possible. So I'm trying to refactor out all the similar code into their own functions, but aren't sure where to place these functions.
Current setup:
var module = function module( API ) {
var properties,
doSomething = function doSomething( config ) {
if (A) {
foo();
}
else if (B) {
// lotsa bar1 code
}
else if (C) {
// lotsa bar2 code
}
else {
error();
}
};
return {
// public interface
};
};
I would like to fold the bar1 and bar2 code into its own function, but can't decide where to place this function. I don't really want to cause overhead by declaring the helper inside the function it's helping, although it's the most readable option.
Option A: Make the helper function another direct method of the module.
This seems to be the easiest approach, but I don't like 'polluting' my main module namespace with functions
"that don't represent a method of the module."
edit: "that don't represent an action of the module."
var module = function module( API ) {
var properties,
bar = function bar() {
// help doSomething
},
doSomething = function doSomething( config ) {
if (A) {
foo();
}
else if (B) {
bar(B);
}
else if (C) {
bar(C);
}
else {
error();
}
};
return {
// public interface
};
};
Option B: Create a seperate namespace for all the helpers. This is how I usually structure these kinds of extra functions, but the more I use this version, the less satisfying it seems.
var module = function module( API ) {
var properties,
helpers = {
'bar' : function bar( input ) {
// help doSomething
}
},
doSomething = function doSomething( config ) {
if (A) {
foo();
}
else if (B) {
helpers.bar(B);
}
else if (C) {
helpers.bar(C);
}
else {
error();
}
};
return {
// public interface
};
};
Option C: Set the helper function as a method of the main function.
var module = function module( API ) {
var properties,
doSomething = function doSomething( config ) {
if (A) {
foo();
}
else if (B) {
doSomething.bar(B);
}
else if (C) {
doSomething.bar(C);
}
else {
error();
}
};
doSomething.bar = function( input ) {
// help doSomething
};
return {
// public interface
};
};
And option D would be to create a closure around the function.
Maybe I'm putting way too much thought in this and it's all a matter of preference.
Related
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
I am not sure if this is possible at all, how ever given this article I am curious as to how a function such as:
export default () => {
let _foo = '';
return {
set foo(x) {
if (x === undefined) {
_foo = this.someFN();
} else {
_foo = x;
}
},
get foo() {
return _foo;
},
someFN() {
return 'hello'
}
}
}
There is a concept of, in the article, that there is no "reference to this" in factory functions. If this is the case how do you chain multiple factory functions together?
For instance I am working on a concept where I have written a factory function that has methods which allow you to Chain, an example would be:
const fooBar = FooBar();
fooBar.someMethod().someOtherMethod();
This works because I return this. Are you to avoid "this" in factory functions? and **Are factory functions meant to only have one method in them?
So in the case of my example above, would it be wrong to have someFN() there?
There's no hard and fast rule that you can't use this in factory functions. But if you wanted to avoid it, just remember your object in a variable and use that instead (which also avoids issues with the function being called with the wrong this):
export default () => {
let _foo = '';
let obj = {
set foo(x) {
if (x === undefined) {
_foo = this.someFN();
} else {
_foo = x;
}
},
get foo() {
return _foo;
},
someFN() {
return 'hello'
},
chainableMethod1() {
// Do something, then
return obj;
},
chainableMethod2() {
// Do something else, then
return obj;
}
};
return obj;
};
Usage:
theModule.chainableMethod1().chainableMethod2();
How can I check if a private function exist inside an object?
var myObj = function(){
var myFunc = function(){};
var init = function(){
//has myFunc been defined?
}
}
I know that I can do this:
if (typeof myFunc == 'function') {
//myFunc exist
}
But this is checking the global scope.
How can I limit this to my objects scope?
Here is the most simplified case that i need:
var myComponent = function () {
var exportExcel = function () {
};
this.export = function (type) {
if('export'+type is a private function in this scope){
window["export"+type]()//but in local scope;
}
}
};
And here is my work around for now :
var myComponent = function () {
var Exports = {
Excel: function () {
}
};
this.export = function (type) {
if (Exports.hasOwnProperty(type)) {
Exports[type]();
} else {
alert('This Export type has not been implemented Yet ! or it never will ... how knows? well i don\'t ...');
}
}
};
As you probably noticed:
function myFunc () {};
function myObj () {
function init () {
if (myFunc) // passes
};
}
You could cheat a bit :-|
function myObj () {
var isdef = { myFunc: true };
function myFunc () {};
function init () {
if (isdef.myFunc) // do something
};
}
I wonder why one would do that though.
Bases on the extra information given, the most practical pattern is what you're calling the "temporary workaround": keeping your functions in a private object, keyed by type.
var myComponent = function () {
var exporters = Object.create(null, {
"Excel": function () {
// do magic export here
}
});
this.export = function (type) {
if (type in exporters) {
// defined locally
return exporters[type].call(this); // binding is optional
} else {
// no export for you!
}
}
};
This prevents two things:
Referencing the function via string composition,
Querying the global scope (or, actually, any scope in between your component and the global scope).
This may not be your design principle, you could further extend this code to allow for adding / removing exporters.
Below is the code I have used to achieve interface concept in javascript:
function Interface1(ImplementingClass) {
return {
implementedFunction : ImplementingClass.implementedFunction
}
}
function Interface2(ImplementingClass) {
return {
implementedFunction : ImplementingClass.implementedFunction
}
}
function ImplementingClass() {
this.implementedFunction = function() {
// How to get implemented interface name, for
// example here interface name should be Interface1???
}
}
function Test() {
this.test = function() {
return new Interface1(new ImplementingClass());
}
}
var test = new Test();
test.test().implementedFunction();
Question: How to get interface name in implemented function, for example in java we use instance of operator
if(this instance of Interface) {
// Do something
}
No, instanceof won't work - it's only for prototypical inheritance from a constructor function's prototype object. If you need information about your interface, you will need to place it on your interface object:
function Interface(implementingInstance) {
return {
interfaceName: "MyInterface",
implementedFunction : implementingInstance.implementingFunction
}
}
function ImplementingClass() {
this.implementingFunction = function() {
console.log(this.interfaceName);
}
}
/* maybe helpful:
ImplementingClass.prototype.interfaceName = "noInterface"; // real instance
*/
function Test() {
this.test = function() {
return Interface(new ImplementingClass());
}
}
new Test().test().implementedFunction();
// calls `implementingFunction` on the object with the `interfaceName` property
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