This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 7 years ago.
I have the following script:
(function () {
var Module = (function () {
var fctToCall = function () {
alert('Foo');
};
return {
fctToCall: fctToCall
};
})();
var Module2 = (function () {
var init = function () {
var str = 'fctToCall';
Module.str(); // here
};
return {
init: init
};
})();
})();
So I want to call this fctToCall method by its name - how can I do that? So far I know 3 methods:
by attaching the function to the window object, but then it wouldn't be local and in closure, and I wouldn't have the access to other local variables
eval, the best options as far as I see it, but it's still eval, so I don't wanna use it
this, but it's another architecture, I don't wanna change it
How can I solve this?
To call function use
Module[str]();
As Module is an object, you can access the dynamic properties and methods of it by using the bracket notation.
(function() {
var Module = (function() {
var fctToCall = function() {
console.log('Foo');
};
return {
fctToCall: fctToCall
};
})();
var Module2 = (function() {
var init = function() {
var str = 'fctToCall';
// Call as
Module[str]();
};
return {
init: init
};
})();
Module2.init();
})();
Replace:
var init = function () {
var str = 'fctToCall';
Module.str(); // here
};
With:
var init = function () {
var str = 'fctToCall';
Module[str](); // here
};
Here, str is used as key to access the fctToCall function on Module.
Then you can call Module2.init(), in your IIFE:
(function() {
var Module = (function() {
var fctToCall = function() {
document.write('Foo'); // (alert is broken in snippets)
};
return {
fctToCall: fctToCall
};
})();
var Module2 = (function() {
var init = function() {
var str = 'fctToCall';
Module[str](); // Access & call `fctToCall`.
};
return {
init: init
};
})();
Module2.init(); // Call `init`.
})();
Since everything in JS is object you can use the object notation.
Module[str]();
You can just invoke the function like this:
Module[str]();
Related
In specs/Test.js is a test definition: "regex2"
In pages/TablePage.js is a page object
in regex2 there is a try to use a function from TablePage.js
it('regex2', function(){
table_page.matchPriceRegex(table_page.workingBalanceField)
});
it is saying table_page.matchPriceRegex is not a function
The function itself from TablePage.js:
var TablePage = (function () {
function TablePage() {
this.workingBalanceField = element(By.xpath('//*[#id="root"]/main/section/div/div/div[5]/div/div[1]'));
}
TablePage.prototype.matchPriceRegex = function (locator) {
this.text = locator.getText();
expect(this.text).toMatch("\d{0,3}?,?\d{0,3}?\.?\d{0,3}?");
};
});
module.exports = TablePage;
The require's are incorporated with the spec file so it should see it
var TablePage = require("./../pages/TablePage");
var table_page = new TablePage();
var protractor = require("protractor");
var jasmine = require("jasmine-node");
var browser = protractor.browser;
var number = 0;
When in my IDE(WebStorm) I hold ctrl and click on the function name it redirects me correctly, as it sees it
The typeof the functions or variables form TablePage is undefined
Do you know where is the problem?
The error comes from TablePage.js, it should be.
var TablePage = (function () {
function TablePage() {
this.workingBalanceField = element(By.xpath('//*[#id="root"]/main/section/div/div/div[5]/div/div[1]'));
}
TablePage.prototype.matchPriceRegex = function (locator) {
this.text = locator.getText();
expect(this.text).toMatch("\d{0,3}?,?\d{0,3}?\.?\d{0,3}?");
};
return TablePage; // return the class as outer function return value
})();
// `(function(...){})` return a function, you should use `()` to execute the
// return function to get the returned class: TablePage.
module.exports = TablePage;
I am not very good in JavaScript. so when I saw a block of code now then many area is not clear. So someone please help me to understand.
I know this below way people declare their module
var Module = (function () {
var privateMethod = function () {
//A Private Method
var privatemember; // scope is only private method
};
return {
publicMethod: function () {
//you can call private method here.
}
};
})();
Module.publicMethod(); //works
Just I saw another bit different code for module pattern as follows where knockout.js is used.
var HMS = HMS || {};
$(function () {
HMS.PatientModel = function () {
this.Patient_Name = ko.observable();
this.Patient_Address = ko.observable();
};
HMS.PatientViewModel = function () {
var patient = ko.observable(),
loadPatient = function () {
var newModel = new HMS.PatientModel();
newModel.Patient_Name("Premkumar");
patient(newModel);
};
return {
patient: patient,
loadPatient: loadPatient
};
} ();
HMS.PatientViewModel.loadPatient();
ko.applyBindings(HMS.PatientViewModel);
});
1) What is this code var HMS = HMS || {}; ?
2) See this $(function () {}) ();
Why module has no name specific. see my first code where I give a name to my module like this way var Module = (function () {}) ()
3) Inside module code every function name has started with HMS.............why like HMS.PatientModel = function () { };
Please help me to understand the second set code point wise. Thanks
var HMS = HMS || {};
that expression defines the var HMS to HMS or empty object if it is not defined is a short hand for
if(HMS) {
var HMS = HMS;
} else {
var HMS = {};
}
2) You are creating an object from an IIFE
They are declaring and empty object if it does not exist, and decorating it with the methods/functions once the function below its executed.
is the same as this:
var HMS = {
PatientModel : function () {},
PatientViewModel : function () {},
}
3) And that is why they use HMS inside the function.
var HMS = {};
HMS.PatientModel = function() {};
HMS.PatientViewModel = function() {};
You should read about Closures, IIFE, and How to “properly” create a custom object in JavaScript?
Sample and short explanation of closure:
A closure is when you have access to variables that are not in the lexical scope of the function For example, a function declared inside another function, will have access to the parent variables.
eg:
(function(){
var a = 1;
function mainFunction() {
function innerFunction() {
var b = 2
function subFunction() {
console.log(a); //We have access to "a" here.
console.log(b); //We have access to "b" here.
}
subFunction();
}
innerFunction();
console.log(a); //We have access to "a" here.
console.log(b); //We dont have access to "b" here. //error
}
mainFunction();
})();
console.log(a); //We dont have access to "a" here. //error
1) what is this code var HMS = HMS || {}; ?
If HMS is undefined HMS is to be equal to an empty object otherwise use HMS as is (in your case HMS is an object).
2) see this $(function () {}) ();
It's called IIFE.
3) why like HMS.PatientModel = function () { };
HMS is an object and just adding its property with value. Value may be anything.
4) From your comment in another answer, why they didn't define module name?
They have defined the module name as Module. See var Module = (function(){}());
I'm trying to use a singleton pattern but I am having trouble with implementing a recursive public function.
var singleton = (function(){
var self = this;
function privateFunc(){
console.log('I can only be accessed from within!');
}
return{
publicFunc: function(){
//More stuff here
setTimeout(self.publicFunc, 1000);
}
}
})();
I am calling it with singleton.publicFunc
I get this error Uncaught TypeError: Cannot call method 'publicFunc' of undefined.
My understanding is var self is actually the Window object in this instance, so I have to pass singleton.publicFunc as the callback for this to work, but it doesn't seem very "DRY" (Don't repeat yourself). Is there
a better way to accomplish this while using a singleton?
With API calls
var wikiAPI = (function(){
var self = this;
return {
getRandomArticle : function() {
return $.getJSON("http://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=extracts&exintro=&format=json&callback=?", function (data) {
});
},
fireAPICalls : function() {
self.getRandomArticle().done(function(data) {
for(var id in data.query.pages) {
this.data = data.query.pages[id];
}
console.log(this.data);
setTimeout(self.fireAPICalls, 1000);
});
}
}
})();
You can use a named function expression like so:
var singleton = (function(){
var self = this;
function privateFunc(){
console.log('I can only be accessed from within!');
}
return{
publicFunc: function nameVisibleOnlyInsideThisFunction(){
//^-------------------------------^
//More stuff here
setTimeout(nameVisibleOnlyInsideThisFunction, 1000);
}
}
})();
I just saw your edit. What would help is having a reference to the functions you are trying to call. So how about something like this:
var wikiAPI = (function(){
var self = this;
var randomArticle = function() {
return $.getJSON("http://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=extracts&exintro=&format=json&callback=?", function (data) {
});
};
var repeatFunc = function fireApi() {
randomArticle().done(function(data) {
for(var id in data.query.pages) {
this.data = data.query.pages[id];
}
console.log(this.data);
setTimeout(fireApi, 1000);
});
};
return {
getRandomArticle : randomArticle,
fireAPICalls : repeatFunc
}
})();
Use bind in the setTimeout() to bind the function to the right scope:
publicFunc: function() {
setTimeout(this.publicFunc.bind(this), 1000);
}
Demo: http://jsfiddle.net/te3Ru/
You can't use this in a IIFE. If you want to use this properly you need to create an object/instance of a function, like so:
var singleton = (function () {
// allow to omit "new" when declaring an object
if (!(this instanceof singleton)) return new singleton();
var self = this, // self now points to "this"
privateFunc = function () {
console.log('I can only be accessed from within!');
};
this.publicFunc = function() {
console.log(this); // this now points to the correct object
setTimeout(function () {
self.publicFunc.call(self); // call function in the "self" scope
}, 1000);
};
return this;
});
singleton().publicFunc();
it's not much of a singleton now, but you can have the closest thing to private and public that javascript has!
I'm trying to call a private function inside the revealing pattern. This is my code:
var module = (function(){
var privateMethod = function(val) {
console.log(val);
}
var publicMethod = function() {
var functionString = "privateMethod";
/** This what I tried
functionString.call('test');
window[module.privateMethod]('test');
*/
}
return {
init: publicMethod
}
})();
$(document).ready(function(){
module.init();
});
Someone could help me?
Thanks!
Make your private functions properties of an object?
var module = (function(){
var privateFuncs = {
privateMethod: function(val) {
console.log(val);
}
};
var publicMethod = function() {
var functionString = "privateMethod";
privateFuncs[functionString]('test');
};
return {
init: publicMethod
};
})();
Your other attempts both fail, for different reasons:
functionString.call('test') will never work because functionString refers to a string literal. It doesn't have a call method.
window[module.privateMethod]('test') won't work because firstly, module doesn't have a property privateMethod. It wouldn't be "private" if it did. That means you're attempting to invoke window[undefined], which is not a function.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Javascript outer scope variable access
I have a javascript module that looks something like below. The main issue I'm having is how to access variables in the "this" scope from the private someOtherFunc. Is there a way to access this.myvar in the private someOtherFunc
var mymodule = (function(){
return {
MyObj : function() {
this.myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
//this doesn't seem to work
this.myvar = 456;
};
}
}
}
The idea is that I want to be able to do something like
new mymodule.MyObj().publicfunc, but make the someOtherFunc private
Forget my previous answer. You can do this just by adding a private version of this.
var mymodule = (function() {
return {
MyObj : function() {
this.myvar = 123;
var that = this;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
that.myvar = 456;
};
return this;
}
};
});
Bear in mind that, with your code, every time you call MyObj you get a new object.
So this would do what you want:
>var o = new mymodule().MyObj()
>o.myvar
123
>o.publicfunc()
>o.myvar
456
but not this
>var m = new mymodule()
>m.MyObj().myvar
123
>m.MyObj().publicfunc()
>m.MyObj().myvar
123
If that's not what you want, consider doing something like this
var mymodule = (function() {
var myObj = null;
this.MyObj = function() {
if(myObj != null)
return myObj;
myObj = {};
myObj.myvar = 123;
myObj.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
myObj.myvar = 456;
};
return myObj;
};
});
Declare myvar using the var keyword, making it private, then access it without the this.:
function MyObj(){
var myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function(){
alert(myvar);
};
}
var o = new MyObj();
o.publicfunc();
If you need public access to myvar then create a public getter/setter.
jsFiddle Demo
I think what you're looking for is a way to encapsulate myvar for changes. When some of the other answers run, myvar usually will stay as 123 because the initially returned object from mymodule holds on to that initial value.
Return a function that gets the value of myvar even after it's been modified, and I think that helps your problem.
Here's the code that works for me:
var mymodule = (function(){
var myvar = 123,
publicfunc = function() { myvar = 456 },
getMyVar = function() { return myvar; };
return {
someOtherFunc : publicfunc,
myPublicVar : getMyVar
};
}());
mymodule.someOtherFunc();
alert(mymodule.myPublicVar()); //gives you 456
JSFiddle here.
I hope this helps.
Why not build it a little more deliberately?
// this one returns an object used like:
// myModule.myInt; /* 456 */
// myModule.myFunc(); /* 124 */
var myModule = (function () {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) { return num + 1; },
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
}());
I went through the trouble of explicitly naming the returned, public object, but it's now very clear what is and isn't public, and yet, each one of those things will have access to the variable versions of one another, with the one exception being that if you change myModule.myInt or publicData, they will no longer be equal.
To demonstrate what I mean in the comments below, creating multiple instances with their own private data/methods, I just add in one more layer of function-scope:
var myModule = (function () {
var static_int = 789,
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
You now use it like:
var newModule = myModule(/* instance parameters */);
newModule.myFunc();
...or
var num = myModule(/* instance parameters */).myFunc();
If you wanted to save memory, you could have static helper functions inside of the static-layer:
var myModule = (function () {
var static_int = 789,
static_addOne = function (num) { return num + 1; },
static_divideBy = function (dividend, divisor) { return dividend/divisor; },
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
And now you have "private" functions which are only written one time (ie: you save memory), but any instance can use those functions.
Here's the catch:
Because of how scope and closure work, the static functions have NO access to values inside of the instance (functions inside have access to the static functions, not the other way around).
So, any static helper functions MUST have the values passed to them as arguments, and if you're modifying a number or a string, you MUST return the value out of that function.
// inside of a private method, in any instance
var privateString = "Bob",
privateFunc = function () {
var string = static_helper(privateString);
privateString = string;
//...
};
You don't return anything from MyObj.
return this;
should fix it.
Use the bind method:
var someOtherFunc = function() {
this.myvar = 456;
}.bind(this);