Dependency injection in JavaScript doesn't work - javascript

I want to write a function createCoffee that accepts a function argument called knowHow
function createCoffee(knowHow){
var x=new knowHow(coffee,beans,milk,sugar);
knowHow.create();
}
This is so that I can have different knowHow for how to create the coffee.
Then I write a sample knowHow function
var x=function oneWay(a,b,c,d){
console.log(a+b+c+d)
};
I pass x to createCoffee
Then
a=5;b=1;c=2;d=2;
createCoffee(x);
This should createCoffee according to the specified knowHow.
I expected that the result would be logging in the sum of the variables. Does it have something to do with variable scope.
Is the example logically sound. How can I specify the variables in the oneWay(...) function

Instead of initializing a,b,c,d, do this:
var coffee=5, beans=1, milk=2, sugar=2;

Thanks everyone. I solved my objective in the following way ....
function coffeeMaker(knowHow,coffee,milk,sugar){
knowHow.create(coffee,milk,sugar);
}
var x={create: function oneWay(a,b,c){
console.log(a+b+c);
}};
coffeeMaker(x,2,3,4);
I wanted to make it so that I could do the program according to interface thing as is done in Java.
In Java you can pass reference to an interface and you can have different implementations.
I wanted to achieve the same thing.
In this I can change the knowHow and plug it into the coffeeMaker.
It looks redundant in the present case but when there are like 10 behaviors associated with an object then it becomes useful. I am drawing on the Strategy design pattern for this.

Related

Strange javascript behaviour - error unless 'classes' are defined in correct order

I have a very strange problem with javascript and easel js.
I am using the easel.js library and am already fairly far into the construction of a project using it.
I am attempting to have a 'class' (I know they aren't technically classes in javascript but I will use this terminology for lack of a better word) inherit the Shape class from easel js, and then have another class inherit that. So it would be something like this:
easeljs.Shape --> MenuButton --> BuildingButton
The code I am using looks like this:
BuildingButton.prototype = Object.create(MenuButton.prototype);
BuildingButton.prototype.constructor = BuildingButton;
function BuildingButton(){
MenuButton.call(this);
}
MenuButton.prototype = Object.create(createjs.Shape.prototype);
MenuButton.prototype.constructor = MenuButton;
function MenuButton(){
createjs.Shape.call(this);
}
The problem is that I get the following error with this code:
Uncaught TypeError: undefined is not a function
easeljs-0.7.1.combined.js:8439
(line 8439 is pointing to the initialize() function in the Shape() constructor).
now here's the strange thing. If I change the order of the definitions so that the sub class is defined second and not first, it works fine!
MenuButton.prototype = Object.create(createjs.Shape.prototype);
MenuButton.prototype.constructor = MenuButton;
function MenuButton(){
createjs.Shape.call(this);
}
BuildingButton.prototype = Object.create(MenuButton.prototype);
BuildingButton.prototype.constructor = BuildingButton;
function BuildingButton(){
MenuButton.call(this);
}
This is very confusing as I can't seem to figure out why on earth this is happening. I could just make sure I define them in the correct order and leave it be, but I have all my 'classes' in different source files which are then strung together by grunt, which does so alphabetically.
Also, I feel like I may have a big gap in my knowledge of javascript (or maybe easel.js I'm not sure what exactly is causing this behaviour).
Thanks in advance for your help and I hope the question makes sense!
MenuButton.prototype = Object.create(createjs.Shape.prototype);
…
BuildingButton.prototype = Object.create(MenuButton.prototype);
These two statements have a clear dependency and need to be executed in the correct order (for the function declarations the order is irrelevant if placed in the same scope/file, but if in different files they need to be loaded in the correct order obviously).
I have all my 'classes' in different source files which are then strung together by grunt, which does so alphabetically
That's not a good idea. You should use some build tool/script that allows the declaration of dependencies.
Read this to clear things out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
In first example you try to inherit from nothing, since MenuButton.prototype is not yet defined. To make it work just add MenuButton.prototype = new createjs.Shape.prototype(instead of Object.create() wich shouldn't be used anymore) to instantiate it first before you can you use it. Your first code is like you are willing to eat a banana before having one.

Javascript prototype reflection function

I'm not exactly sure of the name of what I'd like to do but it goes like this:
Currently, I have a bunch of variables in my javascript context that look like $A126 or $B15.
Before running, I have to load in all 9000 of these variables and their current values so later parts of the code can just reference $xxx for the value.
The preloading is not efficient at all and is causing a bottleneck.
As there is a substantial amount of code that uses this $xxx notation I was wondering if it would be possible to make a universal change to $.xxx where $ is a function that performed a lookup of the value passed to it via what was after the period.
So $.xxx would be analogous to GetItem(xxx)
This is for a javascript environment in C# using clearscript, though I don't think that would impact the answer.
It looks like
function Field(val){
var value = val;
this.__defineGetter__("xxx", function(){
return value;
});
this.__defineSetter__("value2", function(val){
value = val;
});
}
var field = new Field("test");
console.log(field.xxx)
---> 'test'
That is almost an example of what I'm looking for. The problem is that I would like to have a general defineGetter that doesn't look for a particular getter by name.

Dynamically Setting a JavaScript Object's Method's Source

I've recently been working on a nice little JavaScript game engine that works a lot like Game Maker, but lets people create basic JavaScript games within a browser. Every instance of every object will have it's own preset methods, which the runner will iterate through and execute. I'm trying to find a way to let the user / creator dynamically edit any of the methods source code. When I say 'preset methods', I mean blank methods stored under specific preset names within the objects / object instances. Here's a basic example:
var newObject = object_add("object_name"); // Adds a new object 'blueprint' and returns the reference.
The function object_add(); creates a JavaScript object, and adds a number of preset methods to it, such as:
create
destroy
step
draw
.. and many more
Each of these methods will have no code in them to start with. I need to let the creator dynamically change any of the methods source code. I could simply overwrite the variable that points towards the method, with a new method, but how can you set method's source code using a string?
I know that something like:
newObject.create = function(){textbox.innerHTML};
definitely wouldn't work. Any ideas?
Many thanks,
Dan.
Looks like you want to use eval function, but it's generally a bad idea.
The answer was found at: Creating functions dynamically in JS
Here's the answer (copied from the other page).
Well, you could use Function, like in this example:
var f = new Function('name', 'return alert("hello, " + name + "!");');
f('erick');
//This way you're defining a new function with arguments and body and assigning it to a variable f. You could use a hashset and store many functions:
var fs = [];
var fs['f1'] = new Function('name', 'return alert("hello, " + name + "!");');
fs['f1']('erick');
//Loading xml depends if it is running on browser or server.
Thanks, #CBroe https://stackoverflow.com/users/1427878/cbroe

OOP - Is it better to call functions from within other functions, or to have one big controller?

I'm re-writing a fairly complex script that I created a few weeks ago. After showing it to a few people, they all agreed that I should break it up into smaller pieces (classes) that have a specific purpose, and SOLID object-oriented programming principles
As a self-taught programmer these concepts are pretty new to me, and I'm a little confused about how to best transfer data from one function/class to another. For instance, here is a simplified structure of what I'm building:
MY QUESTION IS:
Should I have a "controller" script that calls all of these functions/classes and passes the data around wherever necessary? Is this where I would put the for loop from the diagram above, even though it would work just as well as part of Function 1 which could then call Function 2?
Without a controller/service script you'll not be able to meet single responsibility principle in fact. Here's a high level design I'd implement if I were you.
FileRepository
Should expose a method to get a file. Let's name it GetFileById.
MongoDBRepository
Methods for CRUD operations. Such as SelectById, SelectByQuery, Update, Create, Delete.
Object creation logic
If your createNewObj logic is simple it would be enough to move it to your object contructor so that your code looks like that: var newObj = new MyObj(json[i]);
But if it's relatively complex maybe because you use some third party frameforks for validation or whatever you'd better create a factory. Then you could would look this way: var newObj = MyObjFactory.Create(json[i]);
Service/controller
Finally you'll need to implement controller/service object. Let's name it WorkService with a method DoWork which should handle all interactions between the repositories and other objects discribed above. Here's approximately DoWork should look like:
function DoWork(fileId){
var json = fileRepository.SelectById(fileId);
for(var i=0;i<json.length;i++){
var newObj = new MyObj(json[i]); // or calling factory method
var dbRecord = MongoDBRepository.SelectByQuery(newObj.name, newObj.date);
if(dbRecord){
MongoDBRepository.Update(newObj);
}
else{
MongoDBRepository.Create(newObj);
}
}
}
Please note it's just a javascript syntax pseudo-code. Your actual code might look absolutley different but it gives your a feeling of what kind of design your should have. Also I exmplicitly didn't create a repository objects inside DoWork method, think of the way to inject them so you meet Dependency inversion principle.
Hope it helps!

Is it possible to concatenate a function input to text of another function call?

Firstly appologies for the poor title, not sure how to explain this in one line.
I have this Javascript function (stripped down for the purpose of the question)...
function change_col(zone){
var objects= zone1227.getObjects();
}
I am passing in an integer into the function. Where I have "zone1227", I want that 1227 to be the integer I pass in.
I've tried this;
var zonename = "zone" + zone;
var objects= zonename.getObjects();
but that doesn't work.
Is this possible? The functions do exist for every possible integer passed in, but I was hoping to keep the code compact rather than a long list of if statements with hardcoded function names.
Since zone1227 is apparently a global variable, it can also be written as window.zone1227 or as window['zone1227']. This means that you can achieve what you describe, by writing this:
function change_col(zone){
var objects= window['zone' + zone].getObjects();
}
Nonetheless, I agree with Interrobang's comment above. This is not a good way to accomplish whatever it is that you really want to accomplish. You should not be referring to global variables via strings containing their names.
No, you cannot refer to a variable with the value of a string, nor can you concatenate anything onto a variable name. EDIT: turns out you can. You still shouldn't.
Yes, you can avoid using a long hard-coded if/elseif sequence: use an array.
Then you can say this:
function change_col(arr, i)
{
var objects= arr[i].getObjects();
}
And the call would be something like:
change_col(zone, 1227);

Categories

Resources