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 ();
Related
I have this block of code that will create a new instance of MyClass, I want each instances of this class to have an id. So I have a function that will return cnt, and every time the new object is initialized the id value will increase.
var MyClass = (function () {
var Constr, cnt = 0;
Constr = function () {};
Constr.id = function () {
return cnt;
};
Constr.prototype = {
constructor: Constr,
id: Constr.id
};
cnt++
return Constr;
}());
var x = new MyClass();
console.log(x.id);
document.getElementById("1").innerHTML = x.id;
The problem is, I obviously want the value of cnt to be returned, but everything I do returns function() { return cnt; }
Update, deleted fiddle, posted incorrect one.
If you want each instance to have a unique value, then you need to set that value in the constructor for the instance.
You can't inherit the value on the prototype chain. That is what you do when you want every object to have the same value.
You also need to assign the value you want and not a function which will return the value.
Constr = function () {
this.id = cnd;
};
If you want the id to be uniquely assigned for each new instance of your class, then you need to assign the id to your instance data in the Const constructor:
var MyClass = (function () {
var cnt = 0;
// constructor for our object
function Constr() {
// assign a unique id to this object when it is created
this.id = cnt++;
};
// static method (not an instance method) - get current global cnt value
Constr.id = function () {
return cnt;
};
Constr.prototype = {
constructor: Constr,
};
return Constr;
}());
var x = new MyClass();
console.log(x.id);
document.getElementById("1").innerHTML = x.id;
This question shows that perhaps you didn't really understand my comments on your earlier question about the outer function only getting called once. I'd suggest you reread those.
When you do:
x = new MyClass()
it is ONLY executing the Constr function, nothing else. Plus, the .prototype is shared among all instances (that is the point of it) so you can never put a counter there that is unique for each instance.
It seem like all You need is:
var MyClass = (function () {
var cnt = 0;
function Constr() {
this.id = cnt++;
};
Constr.prototype = {
constructor: Constr
};
return Constr;
}());
The following one was my previous BAD answer,
You could replace Constr.id with:
....
Constr.id = new function () {
this.toString = function () {
return ++cnt;
}
};
....
and then You should get it from the instance with
var x = new MyClass();
console.debug(x.id);
but take care that it will be an object and only when used as a string, (like in console.debug, or with .innerHTML= "..." ) will be a string.
Hope it helps.
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.
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;
};
Lets say I have this class:
function classA(n){
this.name = n
}
classA.prototype.getName = function(){
return this.name
}
var x = new classA('john')
console.log(x.getName())
My question is: can I group multiple methods inside a namespace? So I would like to do that:
var x = new classA('john')
console.log(x.CONSTANT.getName())
So I would like to call some methods as x.someMethod() and others as x.CONSTANT.otherMethod()
PS: I'm looking for a cross-browser method. Bind is not working in Safari and IE9.
You can do it, for example, via bind. Google es5 shim for implementation of bind in browsers, which don't support it natively.
function MyClass(name) {
this.name = name;
this.CONSTANT.otherMethod = this.CONSTANT.otherMethod.bind(this);
}
MyClass.prototype.CONSTANT = {
otherMethod: function() {
alert(this.name);
}
};
As far as I know a constant is just a property and it can't contain methods, you need to separate your objects and use methods to have the same effect:
function A (id) {
this.id = id;
this.showId = function () { return this.id; }
};
function B (a) {
this.a = a;
this.getA = function () { return this.a; }
}
var a = new A(12);
var b = new B(a);
b.getA().showId();
edit:
You can use a literal object as follow
function B (id) {
this.id = id;
this.CONSTANT = { otherMethod: function () { alert("..."); } };
someMethod = function () { return this.id; }
}
but the literal CONSTANT object can't access B-object methods,
Consider the #kirilloid post to round this.
You can, but you have to be careful because it won't act like you think it will. The this for the method will be the namespace, not the root object.
For example, in x.CONSTANT.getName(), the this object will be x.CONSTANT, and not x.
Here's some sample code which kinda does what you ask (or in jsfiddle):
function MyClass() {}
MyClass.prototype.CONSTANT = {
getName: function() {
alert('Foo');
}
};
var c = new MyClass();
c.CONSTANT.getName();
To make sure the this is right, you need to do much more.
You can use getters/setters (read this article) to achieve this. For example you may define it like this:
classA.prototype.__defineGetter__('CONSTANT', function() {
var that = this;
return {
getName: function() {
return that.name;
}
};
});
Note that holding reference to the object. It will work now
x = new classA('test');
x.CONSTANT.getName();
// result - test
I currently know two ways to construct singletons in JavaScript. First:
var singleton = {
publicVariable: "I'm public",
publicMethod: function() {}
};
It is perfect except that it does not have a constructor where I could run initialization code.
Second:
(function() {
var privateVariable = "I'm private";
var privateFunction = function() {}
return {
publicVariable: "I'm public",
publicMethod: function () {}
}
})();
The first version does not have private properties nor does it have a constructor, but it is faster and simpler. The second version is more complex, ugly, but has a constructor and private properties.
I'm not in a need for private properties, I just want to have a constructor. Is there something I am missing or are the two approaches above the only ones I've got?
function Singleton() {
if ( Singleton.instance )
return Singleton.instance;
Singleton.instance = this;
this.prop1 = 5;
this.method = function() {};
}
Here is my solution with closures:
function Singleton() {
Singleton.getInstance = (function(_this) {
return function() { return _this; };
})(this);
}
Test:
var foo = new Singleton();
var bar = Singleton.getInstance();
foo === bar; // true
If you are just looking for a place to initialise your singleton, how about this?
var singleton = {
'pubvar': null,
'init': function() {
this.pubvar = 'I am public!';
return this;
}
}.init();
console.assert(singleton.pubvar === 'I am public!');
Simple and elegant.
var singleton = new function() { // <<----Notice the new here
//constructorcode....
this.publicproperty ="blabla";
}
This is basically the same as creating a function, then instantly assiging a new instace of it to the variable singleton. Like var singleton = new SingletonObject();
I highly advice against using singletons this way in javscript though because of the execution order is based on where in the file you place the object and not on your own logic.
What about this?
var Singleton = (function() {
var instance;
// this is actual constructor with params
return function(cfg) {
if (typeof instance == 'undefined') {
instance = this;
this.cfg = cfg;
}
return instance;
};
})();
var a = new Singleton('a');
var b = new Singleton('b');
//a === b; <-- true
//a.cfg <-- 'a'
//b.cfg <-- 'a'
I make it an actual Singleton with static functions and no this like so:
class S {
//"constructor"
static init() {
//Note: Since it's a singleton, there's no "this" instance.
//Instead, you store variables directly on the class.
S.myVar = 7;
}
static myOtherFunc() {
alert(S.myVar);
}
}
//Immediately call init() to make it the "constructor".
//Alternatively, you can call init() elsewhere if you'd
//like to initialize it at a particular time.
S.init();
//Later:
S.myOtherFunc();
S.myVar = 10;