var myclass = {
init:function () {
this.customer = null;
},
test : function(data){
alert(testing);
}
};
I am instantiating myclass like above, and later on I am trying to call a method test of the class, but it doesnt work. What am I doing wrong?
var testClass = new myclass.init();
testClass.customer = 'John B';
testClass.test(); //doesnt alert 1
Instead of getting the alert, for some reason I get this error:
Uncaught TypeError: Object [object Object] has no method 'test'
You have to define your "class" as a constructor function, not an object literal:
var MyClass = function(){
this.init = function () {
this.customer = null;
};
this.test = function(data){
alert('testing');
};
};
var testClass = new MyClass();
testClass.init();
testClass.customer = 'John B';
testClass.test(); //alerts 'testing'
Then the init function is not really needed, you can add that logic to the constructor itself:
var MyClass = function(){
this.customer = null;
this.test = function(data){
alert('testing');
};
};
var testClass = new MyClass();
testClass.customer = 'John B';
testClass.test(); //alerts 'testing'
You can also add your methods to MyClass.prototype instead of declaring them inside the constructor. For the difference between the two, refer to Use of 'prototype' vs. 'this' in JavaScript?.
Finally, if you want to stick to your object literal, you have to use Object.create:
var myclass = {
init:function () {
this.customer = null;
},
test : function(data){
alert('testing');
}
};
var testClass = Object.create(myclass);
testClass.customer = 'John B';
testClass.test(); //alerts 'testing'
Another implementation, with some explanations:
var MyClass = function() {
this.customer = null;
};
// Any functions need to be added to the prototype,
// and should use the keyword this to access member fields.
// Doing this allows for a performance gain over recreating a new function definition
// every time we create the object, as would be the case with this.test = function() { ... }
MyClass.prototype.test = function(data){
alert('testing');
};
// At this point, MyClass is a constructor function with all of it's
// prototype methods set, ready to be instantiated.
var testClass = new MyClass();
testClass.customer = 'John B'; // May also want to consider moving this into the constructor function as a parameter.
testClass.test();
JSFiddle
You have to add the test method a prototype of init. Like this...
var myclass = {
init:function () {
this.customer = null;
},
test : function(data){
alert(testing);
},
};
myclass.init.prototype = myclass;
This way all objects will inherit from myclass object.
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;
};
I want extend a new JS object while creation with other object passing a parameter.
This code does not work, because I only can extend object without dynamic parameter.
otherObject = function(id1){
this.id = id1;
};
otherObject.prototype.test =function(){
alert(this.id);
};
testObject = function(id2) {
this.id=id2;
};
testObject.prototype = new otherObject("id2");/* id2 should be testObject this.id */
var a = new testObject("variable");
a.test();
Any suggestion?
Apart from the obvious syntax error, the correct JavaScript way of inheritance is this:
// constructors are named uppercase by convention
function OtherObject(id1) {
this.id = id1;
};
OtherObject.prototype.test = function() {
alert(this.id);
};
function TestObject(id2) {
// call "super" constructor on this object:
OtherObject.call(this, id2);
};
// create a prototype object inheriting from the other one
TestObject.prototype = Object.create(OtherObject.prototype);
// if you want them to be equal (share all methods), you can simply use
TestObject.prototype = OtherObject.prototype;
var a = new TestObject("variable");
a.test(); // alerts "variable"
You will find lots of tutorials about this on the web.
Fixed your code
otherObject = function(id1){
this.id = id1;
};
otherObject.prototype.test =function(){
alert(this.id);
};
testObject = function(id2) {
this.id=id2;
};
testObject.prototype = new otherObject("id2");/* id2 should be testObject this.id */
var a = new testObject("variable");
a.test();
testObject = function(id2) {
otherObject.call(this, id2); // run the parent object constructor with id2 parameter
this.id=id2;
};
testObject.prototype = new otherObject(); // no id2 parameter here, it doesn't make sense
Note that while creating an instance of testObject, the constructor of otherObject is called twice - once to create the prototype and once to initialise the object.
To prevent duplicate initialisation, we can halt the constructor immediately when we are only using it to create the prototype.
otherObject = function(id1){
if (typeof id1 == 'undefined') {
/* as there is no parameter, this must be the call used to create
* the prototype. No initialisation needed here, we'll just return.
*/
return;
}
this.id = id1;
};
P.S. Please use capital camelcase with objects.
I do not understand exactly what you desire, but
otherObject.prototype.test = function () {
alert(this.id);
};
would be correct.
And this
testObject.prototype = new otherObject(id2);
will not work unless id2 is set before.
Try the following
var OtherObject = function () {
}
OtherObject.prototype.test = function () {
alert (this.id);
}
var TestObject = function (id) {
this.id = id;
}
TestObject.prototype = new OtherObject ();
var a = new TestObject("variable");
a.test ();
This seems to be something that have been discussed by many. But unfortunately, I couldn't find an answer to my issue.
Here is a piece of code on Javascript inheritance (from a book):
function Car() {
var self = this;
self.type = "Car"
self.go = function() {
console.log("Going...");
};
};
Toyota = function() { console.log("Original called"); };
Toyota.prototype = new Car();
Toyota.prototype.constructor = function() {
var self = this;
self.type = "Toyota";
self.go = function() {
console.log("A Toyota car is going...");
}
};
Toyota.prototype.isJapaneseCar = true;
function TestCar() {
console.log("Toyota.prototype.constructor: " + Toyota.prototype.constructor);
var t = new Toyota();
console.log("t.constructor: " + t.constructor);
console.log(t.type);
};
And the output in Firefox console:
Toyota.prototype.constructor: function () {
var self = this;
self.type = "Toyota";
self.go = function () {
console.log("A Toyota car is going...");
};
}
Original called
t.constructor: function () {
var self = this;
self.type = "Toyota";
self.go = function () {
console.log("A Toyota car is going...");
};
}
Car
From the output, it is shown that the new Toyota() call:
var t = new Toyota();
didn't invoke the Toyota.prototype.constructor function as expected, instead it still call the function defined in the first place:
Toyota = function() { console.log("Original called"); };
A post with high upvote count gave a fairly detailed explanation together with examples: it said "3. It executes the constructor function, using the new object whenever this is mentioned." Does the "constructor" mentioned refer to prototype.constructor? How are the following 3 lines related:
Toyota = function() { console.log("Original called"); }
Toyota.prototype.constructor = function() { ...
var t = new Toyota();
[EDIT] What confuses me most is why the constructor (Toyota.prototype.constructor) is not invoked when I call new Toyota()?
The constructor property in prototype object contains a reference to the function that constructs instances of that type of object. Hope I'm not trying to confuse here.
For a string object you would see the constructor property referencing the String function (a.k.a constructor informally.)
console.log("".constructor); // would print function String() { [native code] }
which is why typically we would reassign the class (i.e., the function) constructor property to its own.
Toyota.prototype.constructor = Toyota;
var t = new Toyota();
console.log(t.constructor); // prints function Toyota() { /* definition */ }
Hope that answers your question.
If I have a javascript class that runs some initialization code, it seems logical to put this code at the top, and any methods at the bottom of the class. The problem is, if the initialization code contains a method call, I get a 'undefined' is not a function error. I imagine because the method is defined after the method call. How do people normally structure javascript classes to avoid this? Do they put all the initialization code at the end of the class? For example:
var class = function() {
this.start();
this.start = function() {
alert('foo');
};
};
var object = new class();
causes an error, while:
var class = function() {
this.start = function() {
alert('foo');
};
this.start();
};
var object = new class();
does not. what would be considered a good structure for a javascript object like this?
Here's what I would do
// create a "namespace"
var com = com || {};
com.domain = com.domain || {};
// add "class" defintion
com.domain.MyClass = function(){
var privateFields = {};
var publicFields = {};
privateFields.myFunction = function(){
// do something
}
publicFields.initialize = function(){
privateFields.myFunction();
}
return publicFields;
}
var myClass = new com.domain.MyClass();
myClass.initialize();
of course, you could just make initialize(); "private" and run it before return publicFields;
var class = function() {
this.start();
};
class.prototype.start = function() {
alert('foo');
};
var object = new class();
now you can mess around with start as much as you want in the constructor. but dont use the keyword class as it is a reserved word.
I like http://ejohn.org/blog/simple-javascript-inheritance/ where I feel much more programing OOP.
var myClass = Class.extend({
init: function () {
this.foo();
},
foo: function () {
alert("foo");
}
});
new myClass();
Consider making start a method on class's prototype. This has the bonus of saving memory since all instances of class can share the same start, instead of creating a new start function for each instance.
var class = function() {
this.start();
};
class.prototype.start = function() {
alert('foo');
};
var object = new class();
I actually work a lot with structures like this:
var foo = function() {
// Actual construction code...
start(); // <-- doesn't make a difference if functions are
privateMethod(); // public or private!
// ---------------------------------
function start() {
// ... whatever ...
};
function privateMethod() {
// ... whatever ...
};
// ---------------------------------
// Add all public methods to the object (if start() was only used internally
// just don't assign it to the object and it's private)
this.start = start;
};
Given the following:
var someObject = {};
someObject.prototype.a = function() {
};
someObject.prototype.b = function() {
//How can I call someObject.a in this function?
};
How can I call someObject.a from someObject.b? Thanks.
This will work:
someObject.prototype.b = function() {
this.a();
};
However your definition of someObject is slightly wrong, it should be:
var someObject = function() {};
Test script:
var someObject = function() {};
someObject.prototype.a = function() {
alert("Called a()");
};
someObject.prototype.b = function() {
this.a();
};
var obj = new someObject();
obj.b();
I think you probably meant to do this:
function Thingy() {
}
Thingy.prototype.a = function() {
};
Thingy.prototype.b = function() {
this.a();
};
var someObject = new Thingy();
It's constructor functions, not plain objects, that have a special prototype property. The prototype of a constructor function is assigned to all objects created with that constructor via the new keyword as their underlying prototype, which gives them default properties (which may reference functions, as they do above).