Calling one method from another in a Javascript class - javascript

When defining a class in Javascript, how can I call one method from another one?
exports.myClass = function () {
this.init = function() {
myInternalMethod();
}
this.myInternalMethod = function() {
//Do something
}
}
The code above gives me the following error when executing it:
ReferenceError: myInternalMethod is not defined
I also tried this.myInternalMethod and self.myInternalMethod, but both lead to errors.
What's the right way to do this?

I have created this fiddle http://jsfiddle.net/VFKkC/ Here you can call myInternalMedod()
var myClass = function () {
this.init = function() {
this.myInternalMethod();
}
this.myInternalMethod = function() {
console.log("internal");
}
}
var c = new myClass();
c.init();

this.myInternalMethod() does seem to work, though:
var exports = {};
exports.myClass = function () {
this.init = function() {
this.myInternalMethod();
}
this.myInternalMethod = function() {
//Do something
}
}
var x = new exports.myClass();
x.init();

Is it a private member?
exports.myClass = function () {
this.init = function() {
myInternalMethod();
}
function myInternalMethod() {
//Do something
}
}

Related

Triple nested object functions js

I have an object mainly composed of functions/ methods, much like this (Which should work!):
function thing1(){
this.thing2 = function(){
this.thing3 = function(){
alert();
}
}
}
But
When I call thing1.thing2.thing3(), I get
Cannot read property 'thing3' of undefined
complete pseudocode:
function thing1(){
this.thing2 = function(){
this.thing3 = function(){
alert();
}
}
}
var foo = new thing1();
foo.thing2.thing3();
thing2 doesn't return anything which results in returning undefined.
If you want to write chained functions, you need to return this:
function thing1() {
this.thing2 = function() {
this.thing3 = function() {
alert();
}
return this; // chained
}
}
Generally speaking, it's better to assign methods to a functions prototype if you intend to use it as a constructor. You can still chain functions on the prototype.
function thing1() {
}
thing1.prototype.thing2 = function() {
return this; // chained
};
thing1.prototype.thing3 = function() {
alert('thing3');
return this; // you can make this one chained as well, if you like
};
var t = new thing1();
t.thing2().thing3().thing2().thing3();
If you want to just create a basic chain without requiring parentheses, you could create a separate getter function.
function thing1() {
}
Object.defineProperty(thing1.prototype, 'thing2', {
get: function() {
return this;
}
});
thing1.prototype.thing3 = function() {
alert('thing3');
return this;
};
var foo = new thing1();
foo.thing2.thing3().thing2.thing3();
Those are constructors:
function thing1(){
this.thing2 = function(){
this.thing3 = function(){
alert();
}
}
}
(new (new thing1()).thing2()).thing3()
If you want to call thing1.thing2.thing3() you should format it like this:
function thing1(){
this.thing2 = {
thing3: function(){
alert();
}
}
}
var foo = new thing1();
foo.thing2.thing3()

Javascript inheritance method overriding doesn't work

I have trouble understanding how the method overriding works in Javascript.
In the code below, I have CustomFieldTable class subclassing from Table class, and it both have createList function.
How can I override the createList function from the below code so that createList function from the CustomFieldTable class can be run from the reload function?
Current console output:
'Should be silent overridden createList Function'
Desired console output:
'Custom Field create list'
'obj1'
'obj2'
'obj3'
$(document).ready(function() {
var table = new CustomFieldTable();
table.init();
});
function Table() {
var self = this;
self.table_data = [];
self.reload = function() {
self.table_data = ["obj1", "obj2", "obj3"];
self.createList();
}
self.createList = function() {
alert("Should be silent overridden createList Function");
}
}
CustomFieldTable.prototype = new Table();
CustomFieldTable.prototype.constructor = CustomFieldTable;
function CustomFieldTable() {
var self = this;
self.init = function() {
self.reload();
}
self.createList = function() {
alert("Custom Field create list");
for (var i = 0; i < self.table_data.length; i++) {
alert(self.table_data[i]);
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can restructure this this way:
function myClass() {
// Constructor function
this.myProp = "This is myProp on myClass";
}
myClass.prototype.firstMethod = function() {
document.write("I am firstMethod on myClass<br\>");
}
myClass.prototype.secondMethod = function() {
document.write("I am to be overwritten<br\>");
}
function myExtendedClass() {
// This calls "super" class constructor with the correct "this"
myClass.call(this);
this.myOtherProp = "This is a prop only on my extended class<br\>";
}
// Set with super class prototype and set proper constructor
myExtendedClass.prototype = Object.create(myClass.prototype);
myExtendedClass.prototype.contructor = myExtendedClass;
// Overwrite or set new methods on extended class object
myExtendedClass.prototype.secondMethod = function() {
document.write("I overwrote my super's method<br\>");
}
var a = new myExtendedClass();
console.log(a);
a.firstMethod();
a.secondMethod();
To be exact... a correction of your code would be:
$(document).ready(function() {
var table = new CustomFieldTable();
table.init();
});
function Table() {
this.table_data = [];
}
Table.prototype.reload = function() {
this.table_data = ["obj1", "obj2", "obj3"];
this.createList();
}
Table.prototype.createList = function() {
alert("Should be silent overridden createList Function");
}
function CustomFieldTable() {
Table.call(this);
}
CustomFieldTable.prototype = Object.create(Table.prototype);
CustomFieldTable.prototype.constructor = CustomFieldTable;
CustomFieldTable.prototype.init = function() {
this.reload();
}
CustomFieldTable.prototype.createList = function() {
alert("Custom Field create list");
for (var i = 0; i < this.table_data.length; i++) {
alert(this.table_data[i]);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
A few things to note, when you set these functions inside the constructor you are creating new instances of the function object whenever you create an object. Instead, use the .prototype to set methods on the object. Then use Object.create to extend the prototype and call the super from the constructor.

JQuery function is not defined

this.slideUpComm = function (){
$("#Day-events-content p").addClass("hidden").slideUp("fast");
}
this.showhideEvents = function() {
$("#Day-events-content").on("click", ".eventsToggle", function() {
var obj = $(this).next();
if ($(obj).hasClass("hidden")) {
slideUpComm();
$(obj).removeClass("hidden").slideDown();
} else {
$(obj).addClass("hidden").slideUp();
}
});
}
I would like to use slideUpComm as function that I include on different events but console return Uncaught ReferenceError: slideUpComm is not defined.
How I should pass function to function ? Should I use callback?
function dateObj() {
this.d = new Date();
this.day = this.d.getDate();
this.numDay = this.d.getDay();
this.month = parseInt(this.d.getMonth());
this.year = this.d.getFullYear();
this.slideUpComm = function (){
}
this.showhideEvents = function() {
});
}
}
My Object look like above.
The problem is slideUpComm is a member of an object... so you need to use the object reference to invoke the method
//create a closure varaible to hold the reference to the instance
var self = this;
this.slideUpComm = function (){
$("#Day-events-content p").addClass("hidden").slideUp("fast");
}
this.showhideEvents = function() {
$("#Day-events-content").on("click", ".eventsToggle", function() {
var obj = $(this).next();
if ($(obj).hasClass("hidden")) {
//slideUpComm is a instance property so access it using the instance
self.slideUpComm();
$(obj).removeClass("hidden").slideDown();
} else {
$(obj).addClass("hidden").slideUp();
}
});
}
slideUpComm is a function of dateObj, you can not directly invoke the function. So to invoke a function you need to create an instance of function/object
var a = new dataObj();
then you can invoke the function using
a.slideUpComm()
Could this not be reduced to:
$("<object>").slideToggle();
?

How to maintain reference to an instance, when using the setTimeout callback?

How to maintain a reference to an instance, when using the setTimeout callback? E.G:
In my ViewModel (using Knockout)
var MyVM = function () {
this.myFunc = function () {
setTimeout("this.myCallback()", 2000);
};
this.myCallback = function() { this.myObservable(true); }
}
This fails.
You can add a private field :
var MyVM = function () {
var self = this;
this.myFunc = function () {
setTimeout(self.myCallback, 2000);
};
this.myCallback = function() { self.myObservable(true); }
}
var vm = new MyVM();
Have a look at the RP Niemeyer's answer.
I hope it helps.

Static member inside a function public inside namespace

How to make Static member inside a function public inside namespace
var myNamespace= new function()
{
this.myClass= function Page()
{
this.MyStaticVar = "myValue";
}
}
$("#block").html(myNamespace.myClass.MyStaticVar);
http://jsfiddle.net/DSs6r/97/
Please try it there...
The "namespace" shouldn’t be a function, and this isn’t right in either case.
var myNamespace = {
myClass: function Page() {
}
};
myNamespace.myClass.MyStaticVar = "myValue";
(Updated jsFiddle)
Like this:
var ns = {
Class: {
myStaticVar: 'myValue'
}
};
The main, only really, issue here was that you used a named function instead of an anonymous one (function Page()). Without the name, your code works just fine:
var myNamespace = new function()
{
this.myClass = new function()
{
this.MyStaticVar = "myValue";
};
};
Here is a jsfiddle showing the code working: http://jsfiddle.net/DSs6r/101/
More than likely, you were looking for a setup like this:
var myNamespace = new function()
{
var Page = function(){
var MyStaticVar = "myValue";
var MyDynamicVar = "";
function SetDynamicVar(val){
MyDynamicVar = val;
};
function GetDynamicVar(){
return MyDynamicVar;
}
return{
MyStaticVar: MyStaticVar,
SetDynamicVar: SetDynamicVar,
GetDynamicVar: GetDynamicVar
};
};
this.myClass = new Page();
};
Which would allow stuff like this:
myNamespace.myClass.SetDynamicVar("someValue")
$("#block").html(myNamespace.myClass.GetDynamicVar());
and:
$("#block").html(myNamespace.myClass.MyStaticVar);
Here is the working fiddle: http://jsfiddle.net/DSs6r/102/

Categories