Call function within closure with string in variable - javascript

I know this question has been asked several times on SO but I combed through about 12 questions and none have been able to help me out.
$(document).ready(function () {
var Joe = function(){
function introduce(petname){
alert(petname)
}
return {
introduce:introduce
}
}();
var Jane = function(){
function introduce(petname){
console.log(petname)
}
return {
introduce:introduce
}
}()
}
if I have the word joe stored in a variable how can I call the function
Joe.introduce('pluto')
assuming I have the word Joe stored in a variable fnc
fnc = "Joe";
I don't want to use eval. I have tried window[fnc.introduce('pluto')]()
as others have suggested but it does not work.

Try this! =)
var Joe = function(){
this.introduce = function(pet){
alert(pet);
}
}
var Jane = {
introduce : function(pet){
alert(pet);
}
}
$(function(){
new Joe().introduce('pluto');
Jane.introduce('food');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

The only way I can think to do this is something like this...
Store your functions in an object, then reference the function with object[fnc].
edit: updated original code to reflect OP's edits
fnc = 'Joe';
$(document).ready(function () {
var object = {
Joe: function () {
function introduce(petname) {
alert(petname)
}
return {
introduce: introduce
};
},
Jane: function () {
function introduce(petname) {
console.log(petname)
}
return {
introduce: introduce
};
},
};
object[fnc]().introduce('pluto');
object['Jane']().introduce('goofy');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

javascript prototype function - 'is not a function'

Problem:
I have a piece of code that throws an error: this.isEmpty is not a function,
and I cannot figure out why. Following is the fragment (jsfiddle):
function addAlbumGrid(){
const MainGrid = new AlbumGrid ()
return MainGrid
}
function AlbumGrid() {
MainGrid.call(this)
}
var parentPrototype = Object.create(AlbumGrid.prototype)
parentPrototype.constructor = MainGrid
MainGrid.prototype = parentPrototype
AlbumGrid.prototype.addPhotoBox = function () {
MainGrid.prototype.add.call(this)
}
function MainGrid(){
}
MainGrid.prototype = {
isEmpty: function() {
{
return false
}
},
add:function() {
if(!this.isEmpty())
{
return false
}
}
}
var AlbumGrid=addAlbumGrid()
AlbumGrid.addPhotoBox()
Following is code that works (jsfiddle):
function animal() {
}
animal.prototype = {
canWalk: function () {
return true
},
move: function () {
if(this.canWalk()) {alert ('moving')}
}
}
function bird() {
animal.call(this)
}
var animalProto = Object.create(animal.prototype)
animalProto.constructor = bird
bird.prototype = animalProto
bird.prototype.fly = function () {
animal.prototype.move.call(this)
}
let fluffy = new bird ()
fluffy.fly()
Searching for help I landed at this page, can it be that I am somewhere loosing the context of this, and it is pointing to something I don't want?
In that case, would a solution using composition be an option (object.assign(..))?
Or can it be anything else?
I hope somebody can shed a light.
Thank you...
Ps edit: I have now updated the code, the first 3 comments reflected an older version of this post.

using revealling moduler pattern for complex in javascript

I have a very complex class so i decided to break into sub modules and trying to use revealing modules pattern.
I have main class and decided to divide into smaller container function. but in current scenario
But i am not able to access any internal function from outside i.e callSearchResultWithCallBack using searchFinder.Search.callSearchResultWithCallBack(). which pattern should i use to keep this code clean as well have control to call internal function in sub module.
Thanks
var searchFinder;
function SearchFinder() {
me = this;
this.searchResult = null;
this.init = function() {
declareControls();
createAccordian();
addEvents();
fillControls();
var declareControls = function() {
this.SearchButtons = jQuery('.doSearch');
this.InputLocation = jQuery('#inputLocation');
this.InputDistanceWithIn = jQuery('#inputDistanceWithIn');
this.InputName = jQuery('#inputName');
}
var addEvents = function() {
me.SearchButtons.click(function() {
me.Search();
});
}
var fillControls = function() {
var getGetCategory = function() {
}
}
}
this.Search = function() {
var url = '';
var searchCriteria = {};
validateAndCreateCriteria();
callSearchResultWithCallBack();
function validateAndCreateCriteria() {
function validateAandGetCategory() {
if (SearchValidation.ValidateZipCode(me.InputLocation.val().trim())) {
searchCriteria.location = me.InputLocation.val().trim();
} else if (SearchValidation.ValidateCityState(me.InputLocation.val().trim())) {
searchCriteria.location = me.InputLocation.val().trim();
}
}
}
// need to access it outsite
function callSearchResultWithCallBack() {
me.searchResult(searchCriteria, SearchResultCallBack);
function SearchResultCallBack() {
}
}
}
}
jQuery(function() {
searchFinder = new SearchFinder();
searchFinder.init();
searchFinder.Search.callSearchResultWithCallBack();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
This code has multiple issues, first I will address the fact that for example declareControls is not executing. First declare the function than execute!
this.init = function() {
var declareControls = function() {
this.SearchButtons = jQuery('.doSearch');
this.InputLocation = jQuery('#inputLocation');
this.InputDistanceWithIn = jQuery('#inputDistanceWithIn');
this.InputName = jQuery('#inputName');
}
var addEvents = function() {
this.SearchButtons.click(function() {
me.Search();
});
}
var fillControls = function() {
var getGetCategory = function() {
}
}
declareControls();
//createAccordian(); //not defined
addEvents();
fillControls();
}
Now let's look at others problems that will arise.
the me object referring to this is in the scope of searchFinder and does not refer to the same this in the instance of searchFinder.
function jQuery can be replaced by the commonly used $.
searchFinder.Search.callSearchResultWithCallBack() this is never going to work. Since the Search function is an object and callSearchResultWithCallBack isn't a property of this function.
Solution; make it part of the prototype of Search.
Steps:
Move callSearchResultWithCallBack outside the search function.
Add prototype to Search function
Call function via prototype.
function callSearchResultWithCallBack() {
me.searchResult(searchCriteria, SearchResultCallBack);
function SearchResultCallBack() {
}
}
this.Search.prototype.callSearchResultWithCallBack = callSearchResultWithCallBack;
If you want to fire this function outside of search use this:
searchFinder.Search.prototype.callSearchResultWithCallBack();
Please remember that callSearchResultWithCallBack will throw an error because searchCriteria is undefined.
This fixes your problems for now, but this code has to be revised thoroughly. But this should get you started. http://ejohn.org/blog/simple-javascript-inheritance/

I wanted to make a javascript library function is not working

I wanted to call the run function that should call the other and action will be done on the base of element_id
NGL = {}
NGL.SceneBuilder = function() {
var yamlFile = 'http://example.com/main.yaml'
var parseYaml = function() {
}
var buildScene = function() {
// other code
simulationStarted(element_id);
}
return {
run: function(element_id) {
parseYaml();
buildScene(element_id);
}
}
}
NGL.SceneBuilder.run('#someid');
You're not executing your factory so NGL.SceneBuilder is a function, not an object having the run property. Call the function :
NGL.SceneBuilder = (function() {
...
})(); // <<===
Note also that you forget to declare the element_id parameter in buildScene but maybe is it just for the question.

javascript closure: protecting inner variable

I'm using the revealing module pattern somewhat like this:
var SomeClosure = function () {
var SomeInnerVar = 4;
function InnerGetTheVar() {
return SomeInnerVar;
}
function InitClosure() {
// there's something else happening here that requires me to
// wait for document.ready before initializing the closure
setInterval(IncreaseSomeInnerVar, 10000);
}
function IncreaseSomeInnerVar() {
SomeInnerVar = SomeInnerVar + 1;
}
InitClosure();
return {
GetTheVar: InnerGetTheVar
}
}
$(document).ready(function () {
SomeClosure = SomeClosure();
});
Now why is it that if in the console I type this:
SomeClosure.GetTheVar = 2;
SomeClosure.GetTheVar; // outputs 2!
Why doesn't the closure keep SomeInnerVar protected? I don't want the outer scope to be able to change SomeInnerVar like that.
Thanks for your suggestions.
Actually, SomeInnerVar is still 'protected', in this sense. However, you are overwriting SomeClosure's GetTheVar attribute with the value 2, which isn't 'protected' in the same sense. In other words, you aren't modifying SomeInnerVar, you're modifying GetTheVar.
Instead of just returning an object literal, use Object.defineProperty:
var out = {};
if ( Object.defineProperty ) {
Object.defineProperty(out, 'GetTheVar', {
value: InnerGetTheVar,
writable: false
});
} else {
out.GetTheVar = InnerGetTheVar;
}
return out;

Javascript Object Confusion

I've confused myself nicely here. My scenario is as follows:
function DesignPad() {
function EditBar() {
...
this.removeHandler = function() {
**// how do I call Dragger.removeAsset**
}
}
function Dragger(){
...
this.removeAsset = function() {}
}
this.init = function() {
this.editBar = new EditBar();
this.dragger = new Dragger();
}
}
var dp = new DesignPad();
...
I can't seem to call Dragger.RemoveAsset. I understand the why, my question is how do I call it?
I'm trying to keep like-things separated (e.g. Dragger / EditBar) but I seem to get all sorts of mixed up in my event handlers. Any suggestions, good reading materials, etc. on this stuff?
I found Douglas Crockford's Javascript to be the best introduction to JavaScript. Especialy videos for Yahoo, like: The JavaScript Programming Language where you can learn how exactly are objects created and inherited in JS.
Solution to you problem is:
function DesignPad() {
var that = this;
function EditBar() {
this.removeHandler = function() {
print("RemoveHandler");
that.dragger.removeAsset();
}
}
function Dragger() {
this.removeAsset = function() {
print("RemoveAsset");
}
}
this.init = function() {
this.editBar = new EditBar();
this.dragger = new Dragger();
}
}
var dp = new DesignPad();
dp.init();
dp.editBar.removeHandler();
But as others noticed you could refactor some things :).
To me it just looks like you should refactor that code to make it simpler.
I think that your issue comes from the fact that a nested function is private, so you can't access it from outside.
Is an instance of Dragger a 'property' of your DesignPad object? If so, you could pass a reference to that object into your removeHandler() method.
Try this:
function DesignPad() {
function EditBar(s) {
super = s;
this.removeHandler = function() {
alert('call 1');
super.dragger.removeAsset();
}
}
function Dragger(s){
super = s;
this.removeAsset = function() {
alert('call 2');
}
}
this.init = function() {
this.editBar = new EditBar(this);
this.dragger = new Dragger(this);
}
}
var dp = new DesignPad();
dp.init()
dp.editBar.removeHandler();
alert('end');

Categories

Resources