Javascript calling public method from private one within same object - javascript

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
};
} ();

Related

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
};
}

Javascript call prototype function from function inside constructor

I searched for this issue for quite a long time. Din't find any answer to satisfy my question. What I am trying is:
function myClass() {
function privateFunction () {
publicFunction(); //Error
}
}
myClass.prototype.publicFunction = function() {
this.variable = 1;
}
myClass.prototype.publicFunction2= function() {
return this.variable;
}
This is giving me error. I am not getting what the real problem is:
What I tried:
this.publicFunction();
Then:
myClass.publicFunction();
Then:
myClass.prototype.publicFunction();
This works but it overrides for each object. Acts as if it is static across different JS objects.
You haven't declared the prototype functions correctly. You are also missing the this keyword when calling the function publicFunction.
The private function (privateFunction) is not a member of the class, so if you want to call it as a function, you have to specify the context for it.
function myClass() {
function privateFunction () {
this.publicFunction();
}
privateFunction.call(this);
document.write(this.publicFunction2()); // show value in Stackoverflow snippet
}
myClass.prototype.publicFunction = function() {
this.variable = 1;
}
myClass.prototype.publicFunction2 = function() {
return this.variable;
}
var myClassPrototype = new myClass();
Wouldn't a closure be enough?
First, I'd rename myClass to MyClass by convention
function MyClass() {
var myInstance = this;
function privateFunction () {
// closure
myInstance.publicFunction();
}
}
MyClass.prototype.publicFunction = function() {
this.variable = 1;
}
MyClass.prototype.publicFunction2= function() {
return this.variable;
}
Now you should be able to instanciate it this way
var myInstance = new MyClass();
Now you can see that privateFunction is never called, and it woud be a bit redundant to call it, but I just tried to show how to technically achieve it.
Try this:
function myClass() {
function privateFunction(obj) {
obj.privilegedFunction1();
};
this.privilegedFunction1 = function () {
this.variable = 1;
};
this.privilegedFunction2 = function () {
privateFunction(this);
};
}
myClass.prototype.publicFunction2 = function () {
return this.variable;
}
var test = new myClass();
test.privilegedFunction2();
console.log(test.publicFunction2());
And this:
function myClass() {
function privateFunction(obj) {
obj.publicFunction1();
};
this.privilegedFunction2 = function () {
privateFunction(this);
};
}
myClass.prototype.publicFunction1 = function () {
this.variable = 1;
}
myClass.prototype.publicFunction2 = function () {
return this.variable;
}
var test = new myClass();
test.privilegedFunction2();
console.log(test.publicFunction2());
You may want to read some about public vs private vs privileged members in Javascript. Like this article: http://javascript.crockford.com/private.html
Key points:
Public (prototype) members have no access to private.
Privileged (this) members have access to private.
Private function may access privileged and public members through the passed context parameter.
You aren't accessing it because it's inside a private function.
Try it like this:
function myClass() {
function privateFunction () {
}
this.publicFunction = function() {
alert('ok')
}
}
then if you do
var obj = new myClass()
obj.publicFunction()
you can see the alert
In order to inherit the class you will need some other things. Here is a complete example.
Now here is the relevant js code. Put it in a file to test it:
function Operators() {
//mandatory
var self = this
//private
var IPT_X = '#x'
var IPT_Y = '#y'
//public
this.x = 0
this.y = 0
this.showOperators = function() {
//use of a private property (IPT_X) and a public property (this.x)
$(IPT_X).val(this.x)
$(IPT_Y).val(this.y)
}
this.clean = function() {
this.x = 0
this.y = 0
// call to a local public method
this.showOperators()
}
this.updateOperators = function(_x, _y) {
// use of a public property when call from
// derived class method is necessary
self.x = _x
self.y = _y
}
}
function Randomizer() {
// mandatory for derived classes
Operators.call(this)
// mandatory for overloaded methods with call to the inherited method
var parentUpdateOperators = this.updateOperators
var self = this
// private
function getRandomNumber() {
return Math.round(Math.random() * 1000)
}
// public
this.updateOperators = function(_x, _y) {
// call to inherited method of superior class
parentUpdateOperators(_x, _y)
// call to method of superior class
self.showOperators()
}
this.populateRandomNumbers = function() {
// call to public local method (this.updateOperators())
// and to a local private method (getRandomNumber())
this.updateOperators(getRandomNumber(), getRandomNumber())
}
// init
this.populateRandomNumbers()
}
// Mandatory for derived classes. Allows access to superior classes with
// more than 2 levels of inheritance ("grandfather" classes)
Randomizer.prototype = Object.create(Operators.prototype)
function Operations() {
Randomizer.call(this)
var self = this
//private
var IPT_RES = '#res'
var BTN_SUM = '#sum'
var BTN_SUBTRACT = '#subt'
var BTN_MULTIPLY = '#mult'
var BTN_DIVISION = '#div'
var BTN_CLEAN = '#clean'
var BTN_RAND = '#rand'
function calcSum() {
return self.x + self.y
}
function calcSubtraction() {
return self.x - self.y
}
function calcMultiplication() {
return self.x * self.y
}
function calcDivision() {
return self.x / self.y
}
function showRes(val) {
$(IPT_RES).val(val)
}
//public
this.sum = function() {
// call to 2 local private methods
showRes(calcSum())
}
this.subtract = function() {
showRes(calcSubtraction())
}
this.multiply = function() {
showRes(calcMultiplication())
}
this.division = function() {
showRes(calcDivision())
}
// init
$(BTN_SUM).on('click', function() { self.sum() })
$(BTN_SUBTRACT).on('click', function() { self.subtract() })
$(BTN_MULTIPLY).on('click', function() { self.multiply() })
$(BTN_DIVISION).on('click', function() { self.division() })
$(BTN_CLEAN).on('click', function() { self.clean() })
$(BTN_RAND).on('click', function() { self.populateRandomNumbers() })
}
Operations.prototype = Object.create(Randomizer.prototype)
var obj = new Operations()
If you're going to test it here is the html code:
X: <input id='x'>
<br>
Y: <input id='y'>
<br>
Res: <input id='res'>
<br>
<input id='sum' type='button' value='+'>
<input id='subt' type='button' value='-'>
<input id='mult' type='button' value='*'>
<input id='div' type='button' value='/'>
<input id='clean' type='button' value='C'>
<input id='rand' type='button' value='Rand'>
don't forget to add the jquery file.
Here is a JSFiddle with that code in it:
http://jsfiddle.net/vqqrf2cb/24/

Maximum call stack size exceeded in javascript

I write a extend method to achieve inheritance in javascript:
function Class() {}
Class.prototype.create = function () {
var instance = new this();
instance.init();
return instance;
}
// extend method
Class.extend = Class.prototype.extend = function (props) {
var SubClass = function () {};
SubClass.prototype = Object.create(this.prototype);
for (var name in props) {
SubClass.prototype[name] = props[name];
}
SubClass.prototype.constructor = SubClass;
if (this.prototype.init) {
SubClass.prototype.callSuper = this.prototype.init;
}
SubClass.extend = SubClass.prototype.extend;
SubClass.create = SubClass.prototype.create;
return SubClass;
}
// level 1 inheritance
var Human = Class.extend({
init: function () {
}
});
// level 2 inheritance
var Man = Human.extend({
init: function () {
this.callSuper();
}
})
// level 3 inheritance
var American = Man.extend({
init: function () {
this.callSuper();
}
})
// initilization
American.create();
Then the develop tool report Maximum call stack size exceeded
I think the callSuper method cause the problem, callSuper call init, and init call callSuper, both with the same context.
But I don't know how to fixed it!
Can anyone could help me? How to set the correct context?
You have a scope problem. Here is the solution:
function Class() {}
Class.prototype.create = function () {
var instance = new this();
instance.init();
return instance;
}
// extend method
Class.extend = Class.prototype.extend = function (props) {
var SubClass = function () {},
self = this;
SubClass.prototype = Object.create(this.prototype);
for (var name in props) {
SubClass.prototype[name] = props[name];
}
SubClass.prototype.constructor = SubClass;
if (this.prototype.init) {
SubClass.prototype.callSuper = function() {
self.prototype.init();
}
}
SubClass.extend = SubClass.prototype.extend;
SubClass.create = SubClass.prototype.create;
return SubClass;
}
// level 1 inheritance
var Human = Class.extend({
init: function () {
console.log("Human");
}
});
// level 2 inheritance
var Man = Human.extend({
init: function () {
console.log("Man");
this.callSuper();
}
})
// level 3 inheritance
var American = Man.extend({
init: function () {
console.log("American");
this.callSuper();
}
})
// initilization
American.create();
The key moment is to wrap init method in a closure:
SubClass.prototype.callSuper = function() {
self.prototype.init();
}
Here is a jsfiddle containing the solution http://jsfiddle.net/krasimir/vGHUg/6/

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

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/

Inheriting a class that has the same constructor but different/similar prototypes

Suppose I have a constructor:
function Constructor(input) {
this.input = input
}
Constructor.prototype.method = function() {
console.log('a')
}
But I want to make another class using a copy of the constructor, but changing the prototypes.
function Constructor2(input) {
this.input = input
}
Constructor2.prototype.method = function() {
console.log('b')
}
I don't want to redefine the constructor. How would you do this? Ideally it would be something as simple as:
var Constructor2 = inherits(Constructor)
Constructor2.prototype.method = // overwrite the inherited `method()`
var inherits = function(childCtor, parentCtor) {
/** #constructor */
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.superClass_ = parentCtor.prototype;
childCtor.prototype = new tempCtor();
/** #override */
childCtor.prototype.constructor = childCtor;
};
// How to use it:
var Constructor1 = function() {
//add all your methods, variables etc
};
Constructor1.prototype.myMethod = function() {
};
var Contructor2 = function() {
Contructor1.call(this); // Call the super class constructor
};
inherits(Contstructor2, Constructor1);
// Constructor2 now inherits from Constructor1
// override, add methods variables etc, whatever you need.
// Have fun!
Okay, much easier just to use apply:
function newConstructor(Super) {
function Construct() {
Super.apply(this, arguments)
}
require('util').inherits(Construct, Super)
return Construct
}
Here's a nasty-ish solution:
function Constructor1(input) {
this.input = input;
}
Constructor1.prototype.method = function() {
console.log('a');
}
// be careful here: evals the string value of Constructor1 with references to "Constructor1" changed to "Constructor2"
eval(Constructor1.toString().replace("Constructor1", "Constructor2"));
Constructor2.prototype.method = function() {
console.log('b');
}
var c1 = new Constructor1(1);
var c2 = new Constructor2(2);
console.log(c1.constructor === c2.constructor) // true
c1.method() // a
c2.method() // b

Categories

Resources