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.
Related
I'm trying to make two instances (constructorOne and constructorTwo) of a function variable called myObjectConstructor. For some reason I get the same result back for both instances when I call getProperty.
//this is one other way of creating a Constructor function
var myObjectConstructor = function(){
this.myProperty = '';
init = function(str) {
this.myProperty = str;
},
getProperty = function() {
return this.myProperty;
}
return {
init: function () {
return init.apply(self, arguments);
},
getProperty: function () {
return getProperty.apply(self, arguments);
}
}
}
//instantiate our Constructor
var constructorOne = new myObjectConstructor();
//change myProperty of the first instance
constructorOne.init('this is property one');
//instantiate a second instance of our Constructor
var constructorTwo = new myObjectConstructor();
constructorTwo.init('this is property two');
Both constructorOne.getProperty() and constructorTwo.getProperty() will alert "this is property two":
alert(constructorOne.getProperty()); //this will alert 'this is property two'
alert(constructorTwo.getProperty()); //this will still alert 'this is property two'
Here is a demo.
Question is, why does constructorOne.getProperty() not return 'this is property one'?
self is undefined so inside the init function, this is window, so you are always modifying properties of the same object.
You seem to be doing some weird hybrid of the module pattern and standard JavaScript constructor functions. I strongly suggest picking one of the two approaches and sticking to it.
function MyObjectConstructor(){
this.myProperty = '';
}
MyObjectConstructor.prototype.init = function(str) {
this.myProperty = str;
};
MyObjectConstructor.prototype.getProperty = function() {
return this.myProperty;
};
//instantiate our Constructor
var constructorOne = new MyObjectConstructor();
//change myProperty of the first instance
constructorOne.init('this is property one');
//instantiate a second instance of our Constructor
var constructorTwo = new MyObjectConstructor();
constructorTwo.init('this is property two');
//alert current myProperty of constructorOne instance
alert(constructorOne.getProperty());
//alert current myProperty of constructorTwo instance
alert(constructorTwo.getProperty());
or
function myModule (){
var myProperty = '';
return {
init: function (str) {
myProperty = str;
},
getProperty: function () {
return myProperty;
}
};
}
//instantiate our Constructor
var constructorOne = myModule();
//change myProperty of the first instance
constructorOne.init('this is property one');
//instantiate a second instance of our Constructor
var constructorTwo = myModule();
constructorTwo.init('this is property two');
//alert current myProperty of constructorOne instance
alert(constructorOne.getProperty());
//alert current myProperty of constructorTwo instance
alert(constructorTwo.getProperty());
A better way of doing this would be using proper prototypes:
function MyObjectConstructor() {
this.property = '';
}
MyObjectConstructor.prototype.init = function(newProperty) {
this.property = newProperty;
};
MyObjectConstructor.prototype.getProperty = function() {
return this.property;
};
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();
?
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
}
}
I want to write a small game using JavaScript and <canvas> but first I want to nail the "correct" or at least common approach to working with Objects.
One topic I am having trouble understanding in particular is how I could implement overriding of method.
When I create an Object, I may have this:
function MyObject()
{
var base = {};
base.i = 0;
base.update = function()
{
base.i ++;
}
return base;
}
Then when I create another Object that should start with the same members, I use this:
function AnotherObject()
{
var base = new MyObject();
base.j = 0;
return base;
}
I want to add more content to AnotherObject.update() while still running the logic I have in MyObject.update(), but when I do this within AnotherObject():
base.update = function()
{
j ++;
}
Then I of course lose the logic I added in MyObject.update().
How can I write AnotherObject.update() so that it also calls the original update() method defined by MyObject?
First, I'd suggest you read this excellent excellent MDN article. It will enlighten you.
You can achieve subclassing this way:
function MyObject() {
this.i = 0;
}
MyObject.prototype.update = function() {
this.i++;
}
function AnotherObject() {
MyObject.call(this);
this.j = 0;
}
AnotherObject.prototype = new MyObject;
AnotherObject.prototype.constructor = AnotherObject;
AnotherObject.prototype.update = function() {
MyObject.prototype.update.call(this);
this.j++;
}
obj = new AnotherObject();
console.log(obj.i); //0
console.log(obj.j); //0
obj.update();
console.log(obj.i); //1
console.log(obj.j); //1
console.log(obj instanceof MyObject) //true
console.log(obj instanceof AnotherObject) //true
+1 for zzzzBov's comment. You're using base when you should be using prototype. Not within the constructor function, but rather after the constructor function to further refine the class definition.
function MyObject() {
this.value = 5;
}
MyObject.prototype.update = function() {
this.value++;
}
Var newObject = new MyObject();
newObject.update =function() {
value--;
}
As others have suggested you should follow prototype based inheritance. That is the right way to do it.
But as a solution to what you have done so far you can do as shown below
function MyObject() {
var base = {};
base.i = 0;
base.update = function () {
this.i++;
}
base.show = function () {
console.log("i is " + this.i);
}
return base;
}
function AnotherObject() {
var base = new MyObject();
base.j = 0;
var update = base.update; // proxy variable that refers to original `update`
base.update = function () {
update.call(this); // invoke original `update`
this.j++;
}
var show = base.show; // proxy variable that refers to original `show`
base.show = function () {
show.call(this); // invoke original `show`
console.log("j is " + this.j);
}
return base;
}
var t = AnotherObject();
t.update();
t.show();
How do you go about passing an objects properties in the follwoing situation:
ObjectTest = function()
{
this.var1= "3";
this.var2= "";
}
and the call
ObjectTest .prototype.allFriends = function() {
function bindEvents() {
//pass var1 here
}
}
Is there a way to pass the ObjectTest properties without passing them as properties of the bindEvents(). I'd prefer a global solution if at all possible
You use the same code in the prototype of allFriends as you used in the constructor:
ObjectTest = function()
{
this.var1= "3";
this.var2= "";
}
ObjectTest.prototype.allFriends = function() {
alert(this.var1);
}
It's the same: this.var1 - run this:
ObjectTest = function() {
this.var1 = 3;
this.var2 = "";
};
ObjectTest.prototype.allFriends = function() {
alert(this.var1);
};
x = new ObjectTest();
x.allFriends();
Or see this fiddle: http://jsfiddle.net/9XYZU/
ObjectTest.prototype.allFriends = function() {
do_smth_with(this.var1);
}
Beware, though, that you create a new ObjectTest by calling new ObjectTest(); without the new keyword it will not work.
EDIT: It will still work, because of the inner function will inherit the outer function's (allFriends) scope:
ObjectTest .prototype.allFriends = function() {
function bindEvents() {
console.log(this.var1);
}
}
If it still doesn't work for you, use a reference to the parent's this:
ObjectTest .prototype.allFriends = function() {
var parent = this;
function bindEvents() {
console.log(parent.var1);
}
}