how to call function using name such as "function someName(){}"? - javascript

I have a name of a private function in JavaScript as a string, how do I call that function?
var test = function () {
this.callFunction = function(index) {
return this["func" + index]();
}
function func1() { }
function func2() { }
...
function funcN() { }
}
var obj = new test();
obj.callFunction(1);

func1 and friends are local variables, not members of the object. You can't call them like that (at least not in any sane way).
Define them with function expressions (instead of function declarations) and store them in an array.
var test = function () {
this.callFunction = function(index) {
return funcs[index]();
}
var funcs = [
function () {},
function () {},
function () {}
];
}
var obj = new test();
obj.callFunction(0);

As your code stands, the functions are not present as properties of the instance. What you need to do is create them as properties of the context.
var test = function () {
this.callFunction = function(index) {
return this["func" + index];
}
this.func1 = function() { }
this.func2 = function() { }
...
}
var obj = new test();
obj.callFunction(1)();

you can use eval
var test = function () {
this.callFunction = function(index) {
return eval("func" + index + '()');
}
function func1() {
return 1;
}
function func2() {
return 2;
}
function funcN() { }
};
var obj = new test();
obj.callFunction(2);
eval is evil

You can use a private array of functions:
var test = function() {
var func = [
function() { return "one" },
function() { return "two"; }
]
this.callFunction = function(index) {
return func[index]();
}
}
var obj = new test();
var ret = obj.callFunction(1);
console.log(ret);​
​
http://jsfiddle.net/V8FaJ/

Related

How to get a JavaScript "class" by invoking "new" from another "class"?

We can define a "class" In JavaScript by function, and get its "instance" by the "new" command. Just as follows:
function class_a() {
this.tell = function () {
console.log("This is a_class");
}
}
function class_b() {
this.tell = function () {
console.log("This is b_class");
}
}
var instance_a1 = new class_a();
var instance_b1 = new class_b();
instance_a1.tell();
instance_b1.tell();
My question is: Is there a way to generate these "classes" by the new command from another class? Just like this:
function typex(class_name)
{
...
}
var myclass_a = new typex("class_a");
var myclass_b = new typex("class_b");
var instance_a1 = new myclass_a();
var instance_b1 = new myclass_b();
instance_a1.tell();
instance_b1.tell();
Return the classes from typex but just as reference to the function itself (no invoking inside typex).
Option A: Private classes
function typex(class_name)
{
function class_a() {
this.tell = function () {
console.log("This is a_class");
}
}
function class_b() {
this.tell = function () {
console.log("This is b_class");
}
}
if (class_name === "class_a")
return class_a;
if (class_name === "class_b")
return class_b;
throw new Error("unrecognized classname");
}
Option B: Public classes
function class_a() {
this.tell = function () {
console.log("This is a_class");
}
}
function class_b() {
this.tell = function () {
console.log("This is b_class");
}
}
function typex(class_name)
{
if (class_name === "class_a")
return class_a;
if (class_name === "class_b")
return class_b;
throw new Error("unrecognized classname");
}
Then running the code:
var myclass_a = new typex("class_a");
var myclass_b = new typex("class_b");
var instance_a1 = new myclass_a();
var instance_b1 = new myclass_b();
instance_a1.tell();
instance_b1.tell();
Creates for both the output
This is a_class
This is b_class
Firstly, I end up NOT using the keyword new when calling typex(...), bc I don't want whatever new typex(...) evalutes to to delegate its failed property lookups to typex.prototype.
Secondly, I capitalized MyClass_A and MyClass_B to indicate that they should be paired with the keyword new.
You could just have typex return a constructor function if that is the extent of your use case of these classes/instances.
function typex(class_name) {
var classes = {};
classes.class_a = function() {
this.tell = function() {
console.log('This is a_class');
};
};
classes.class_b = function() {
this.tell = function() {
console.log('This is b_class');
};
};
return classes[class_name];
}
var MyClass_A = typex("class_a");
var MyClass_B = typex("class_b");
var instance_a1 = new MyClass_A();
var instance_b1 = new MyClass_B();
instance_a1.tell(); // "This is class_a"
instance_b1.tell(); // "This is class_b"
instance_a1.constructor === instance_b1.constructor; // false (which is good)
Here's a heavily refactored version that reuses as much code and reduces memory usage as possible.
function typex(class_name) {
var ClassConstructor = function() {
this.class_name = class_name;
};
ClassConstructor.prototype.tell = function() {
console.log('This is ' + this.class_name);
};
return ClassConstructor;
}
var MyClass_A = typex("class_a");
var MyClass_B = typex("class_b");
var instance_a1 = new MyClass_A();
var instance_b1 = new MyClass_B();
instance_a1.tell(); // "This is class_a"
instance_b1.tell(); // "This is class_b"
instance_a1.constructor === instance_b1.constructor; // false (which is good)

Javascript function does not return the right value

So i have this code:
function Class1() {
this.i = 1;
var that=this;
function nn() {
return 21;
}
this.aa = function() {
nn();
};
this.bb = function() {
this.aa();
};
this.cc = function() {
this.bb();
};
}
var o = new Class1();
var b=o.cc();
alert(b); //undefined
But when the alert is fired, I get an undefined error and not 21, Does the private method can not use a return? Thanks!
When using the function() {} syntax to define a function, you always explicitly need to return the value, i.e. not only from nn, but from all intermediate functions as well.
function Class1() {
this.i = 1;
var that = this;
function nn() {
return 21;
}
this.aa = function() {
return nn();
}
this.bb = function() {
return this.aa();
}
this.cc = function() {
return this.bb();
}
}
var o = new Class1();
var b = o.cc();
alert(b); // "21"
Apart from the answer above, the 'this' context seems weird in your functions. Maybe you are better of with arrow functions if you dont want to bind the this context to each function. I also think that it is better to actually separate private and public functions when using a 'class' like this.
function Class1() {
var _nn = function () {
return 21;
}
var _aa = function () {
return _nn();
}
var _bb = function () {
return _aa();
}
var cc = function () {
return _bb();
};
return {
cc
};
}
var o = new Class1();
var a = o.cc();
console.log(a);
Much easier to understand that it is only cc that is a public function.
So with arrow function it would instead look like this, and you can use the Class1 this context inside of your private functions without doing
var that = this; or using bind.
function Class1() {
this.privateThing = 'private';
var _nn = () => { return this.privateThing; };
var _aa = () => { return _nn(); };
var _bb = () => { return _aa(); };
var cc = () => { return _bb(); };
return {
cc
};
}

Can't have access to a variable using call in Javascript

I'm studying Javascript and learning how to use call. I created this script and I don't know why I can't have access to this variable Time.
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {});
var myNewObj = new MyObject.Runner(1000); myNewObj.newTest('1', function() {
console.log(this.time) //output: undefined
});
So how can I get time value inside newTest function?
Issue is in newTest function
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
Here this is pointing to test and not Runner. You will have to save context in a variable and then set it in call.
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
.call + self
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
.bind
As commented, you can even use .bind
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
myFunctionArray.push(execute.bind(this));
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
When you declare your Runner function, you've actually declared a function that takes no arguments that then itself declares a function called Runner that takes one argument.
Actually In this code snippet :
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
this will reference to test variable (as per constructor invocation pattern)
So, to pass right variable cache the value of this in another variable and then pass that to function.

Variables Pointing To The Same Function

I have created a new variable, carBasket and foodBasket, and set them equal to the basketModule() function. They however are pointed to the same function when I want each of these two variables pointed to their own function. I am wondering what should I be doing to achieve this?
var basketModule = (function() {
var basket = [];
return {
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
}
};
}());
carBasket = basketModule;
carBasket.addItem('Audi');
foodBasket = basketModule;
foodBasket.addItem('Ham');
foodBasket.getItemCount(); //outputs 2 instead of 1
You must call a function for each object in order to generate different variables for each one, e.g:
var basketModule = function() {
var basket = [];
return {
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
}
};
};
var carBasket = basketModule(),
foodBasket = basketModule();
carBasket.addItem('Audi');
foodBasket.addItem('Ham');
foodBasket.getItemCount(); // 1
However, in order to reuse the methods for all instances, better use a constructor:
var BasketModule = function() {
this.basket = [];
};
BasketModule.prototype.addItem = function(values) {
this.basket.push(values);
};
BasketModule.prototype.getItemCount = function() {
return this.basket.length;
};
var carBasket = new BasketModule(),
foodBasket = new BasketModule();
carBasket.addItem('Audi');
foodBasket.addItem('Ham');
foodBasket.getItemCount(); // 1
You should consider trying this pattern instead:
var BasketModule = function() {
var basket = [];
return {
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
}
};
};
carBasket = new BasketModule();
carBasket.addItem('Audi');
foodBasket = new BasketModule();
foodBasket.addItem('Ham');
jsfiddle: https://jsfiddle.net/nvsbjset/
This will create separate objects for each basket

Javascript calling public method from private one within same object

Can I call public method from within private one:
var myObject = function() {
var p = 'private var';
function private_method1() {
// can I call public method "public_method1" from this(private_method1) one and if yes HOW?
}
return {
public_method1: function() {
// do stuff here
}
};
} ();
do something like:
var myObject = function() {
var p = 'private var';
function private_method1() {
public.public_method1()
}
var public = {
public_method1: function() {
alert('do stuff')
},
public_method2: function() {
private_method1()
}
};
return public;
} ();
//...
myObject.public_method2()
Why not do this as something you can instantiate?
function Whatever()
{
var p = 'private var';
var self = this;
function private_method1()
{
// I can read the public method
self.public_method1();
}
this.public_method1 = function()
{
// And both test() I can read the private members
alert( p );
}
this.test = function()
{
private_method1();
}
}
var myObject = new Whatever();
myObject.test();
public_method1 is not a public method. It is a method on an anonymous object that is constructed entirely within the return statement of your constructor function.
If you want to call it, why not structure the object like this:
var myObject = function() {
var p...
function private_method() {
another_object.public_method1()
}
var another_object = {
public_method1: function() {
....
}
}
return another_object;
}() ;
Is this approach not a advisable one? I am not sure though
var klass = function(){
var privateMethod = function(){
this.publicMethod1();
}.bind(this);
this.publicMethod1 = function(){
console.log("public method called through private method");
}
this.publicMethod2 = function(){
privateMethod();
}
}
var klassObj = new klass();
klassObj.publicMethod2();
Do not know direct answer, but following should work.
var myObject = function()
{
var p = 'private var';
function private_method1() {
_public_method1()
}
var _public_method1 = function() {
// do stuff here
}
return {
public_method1: _public_method1
};
} ();

Categories

Resources