Why do I get undefined constructor - javascript

I try to follow Stephan Stoyanov book on JavaScript Design Patterns. And one of the examples in this book looks similar to this:
var MyClass = (function () {
var Constr, cnt = 0;
Constr = function () {};
Constr.id = function () {
return "myid-" + cnt;
};
Constr.prototype = {
constructor: MyClass // <-- Please, pay attention
};
return Constr;
}());
However, when I use this code like so:
var tst = new MyClass();
console.log(tst.contructor);
I see undefined in the console. Why is that and how can I fix that?

At the point you assign MyClass to the .constructor property of the prototype, the variable MyClass has not yet been initialized. It won't have a value until after your function is done executing. Instead, you can just assign it Constr since that does have a value and they will be the same value that is eventually assigned to MyClass.
var MyClass = (function () {
var Constr, cnt = 0;
Constr = function () {};
Constr.id = function () {
return "myid-" + cnt;
};
Constr.prototype = {
constructor: Constr // <-- Change to this
};
return Constr;
}());

The problem is here:
Constr.prototype = {
constructor: MyClass // MyClass is undefined right now!
};
The function hasn't completed when it assigns MyClass as the value for the constructor property. At this point MyClass is undefined, so that's what you get.
See this: https://jsfiddle.net/vh45can8/

As written Constr is an anonymous function which already has its prototype object's constructor pointing to itself. I hope the book gives a reason for making things complicated:
var MyClass = (function () {
var Constr, cnt = 0;
Constr = function () {};
Constr.id = function () {
return "myid-" + cnt;
};
return Constr;
}());
works without serious mystery.

Related

Returning the ID of MyClass in Javascript

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.

Create a class, extend from another and call a parent method

First of all, I took the animals example from the coffeescript site.
I want to simulate next things in javascript:
Classes
Public methods only
Private methods and variables only
Inheritance
Call methods from the super class
I think this way to create this is ok, but when I try to get the move method from the parent class, always it returns to itself. What I'm doing wrong?
BTW. Which are the best practices to achieve my goal? Is right what I'm doing?
var Animal = (function() {
function Animal() {}
var _private = {};
var _public = {
move: function() {
console.log('Can move');
}
};
Animal.prototype = _public;
Animal.prototype.constructor = Animal;
return Animal;
})();
var Snake = (function(_super) {
function Snake() {}
var _private = {};
var _public = {
move: function() {
console.log(Snake._super_.move);
console.log('Slithering');
}
};
Snake.prototype = _super.prototype;
Snake._super_ = _super.prototype;
for(var method in _public) {
if(Object.prototype.toString.call(_public[method]) === '[object Function]') {
Snake.prototype[method] = _public[method];
}
}
return Snake;
})(Animal);
var s = new Snake;
s.move();
This is very well written code in my opinion, with just one small mistake.
I think you got your pointers a little crossed, try this:
<script>
var Animal = (function () {
function Animal() { }
var _private = {};
var _public = {
move: function () {
console.log('Can move');
//this just returns a string to show which method was called
//inside of the child's move function's console.log
return "super move called";
}
};
Animal.prototype = _public;
Animal.prototype.constructor = Animal;
return Animal;
})();
var Snake = (function (_super) {
function Snake() { }
var _private = {};
var _public = {
move: function () {
console.log(Snake._super_.move());//Now we can call super's move
console.log('Slithering');
}
};
//This created the circular reference where Snake._super_ was pointing to
//Snake.prototype which was causing the error
//Snake.prototype = _super.prototype;
Snake._super_ = _super.prototype;
for (var method in _public) {
if (Object.prototype.toString.call(_public[method]) === '[object Function]') {
Snake.prototype[method] = _public[method];
}
}
return Snake;
})(Animal);
var s = new Snake;
s.move();//now this outputs "Can move", "super move called", "Slithering"
</script>
If you are asking for best practices, I'd say take any of ready to go solutions on the web. I prefer this one: http://canjs.us/#can_construct.
A few notices about your approach:
It's not reusable. You have to write the same code for every single class. At least you should extract for-loop to make this piece of code reusable.
You need to check _public.hasOwnProperty(method) to make your code more robust.
toString and valueOf methods require special handling since they are non-enumerable in IE<9.
Snake.prototype = _super.prototype; is a complete disaster. Since your super class will have all methods of child.
var F = function(){};
F.prototype = _super.prototype;
Snake.prototype = new F();
Snake.prototype.constructor = Snake;

javascript inheritance with protected variables

Is it possible in javascript to have a variable that is not able to access out side the class's functions, but is able to be accessed by classes that inherit it? I.E:
class1 has protected var x = 4;
class2 inherits class1;
class2.prototype.getVar = function(){return /* parent, uber, super, whatever */ this.x;};
var cl2 = new class2();
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
No. Prototypal inheritance is limited to properties of objects.
Variables within the constructor are only available to other code in that variable scope.
You could probably come up with something like...
function cls1() {
var a = 'foo';
this.some_func = function() {
alert(a);
};
}
function cls2() {
cls1.apply(this, arguments);
var cls1_func = this.some_func;
var b = 'bar'
this.some_func = function() {
cls1_func.apply(this, arguments);
alert(b);
};
}
var x = new cls2;
x.some_func(); // alert "foo" alert "bar"
Or to make it more specific to your pseudo code...
function class1() {
var x = 4;
this.getVar = function() {
return x;
};
}
function class2() {
class1.apply(this, arguments);
var cls1_get_var = this.getVar;
this.getVar = function() {
return cls1_get_var.apply(this, arguments);
};
}
class2.prototype = Object.create( class1.prototype );
var cl2 = new class2;
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
I think you need to use a closure to achieve what your trying to do. Something like this:
Class1 = function() {
var x = 4;
return {
getVar: function() {
return x;
}
}
} ();// executes the function immediately and returns an
//an object with one method - getVar. Through closure this method
//still has access to the variable x
Class2 = function() { };// define a constructor function
Class2.prototype = Class1;//have it inherit from Class1
Cl2 = new Class2();//instantiate a new instance of Class2
console.log(Cl2.x);//this is undefined
console.log(Cl2.getVar());//this outputs 4
This is one of the neat things about javascript in that you can achieve the same things in javascript as you would in a class based language without all the extra key words. Douglas Crockford (always good to consult about javascript) explains prototypal inheritance here
Edit:
Just had a second look at your question.If you want newly created methods in your class to access the variable in the base class then you would have to call the getVar method within your own method.Like such:
Class2 = function() {
this.getVar2 = function() {
return this.getVar();
}
};
console.log(Cl2.getVar2()) //outputs 4

OO Javascript Question

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).

How to make a JavaScript singleton with a constructor without using return?

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;

Categories