I want to create a method which automatically implemented when create an instance of an object, exactly like concept of class constructor.
function myString(string) {
// Storing the length of the string.
this.length = 0;
// A private constructor which automatically implemented
var __construct = function() {
this.getLength();
}();
// Calculates the length of a string
this.getLength = function() {
for (var count in string) {
this.length++;
}
};
}
// Implementation
var newStr = new myString("Hello");
document.write(newStr.length);
I have the following error message when implement the previous code:
TypeError: this.getLength is not a function.
UPDATE:
The problem was in this scope.
The following is constructor method after updade:
var __construct = function(that) {
that.getLength();
}(this);
Bergi's answer in this thread is far more relevant: How to define private constructors in javascript?
Though a bit crude you can create a method called init and then call that method at the bottom of your function so when you instantiate a new object that code shall be run.
function myString(string) {
//Initalization function
this.init = function() {
this.calcLength();
}
// Storing the length of the string.
this.length = 0;
this.getLength = function() {
return this.length;
}
// Calculates the length of a string
this.calcLength = function() {
for (var count in string) {
this.length++;
}
};
this.init();
}
// Implementation
var newStr = new myString("Hello");
var element = document.getElementById('example');
element.innerText = newStr.getLength();
Edit: I'm aware there are better ways to achieve this, but this gets the job done.
Edit 2: Fiddle https://jsfiddle.net/ntygbfb6/3/
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.
I've been stumped on this problem for a few hours now, and I can't seem to find a solution. I have a class that extends a parent class, but I cannot seem to access the variables declared in the parent's constructor.
I borrowed my inheritance technique. It simply uses an "extend" function to create the subclass:
//In functions.js
function extend(base, sub, methods) {
sub.prototype = Object.create(sub.prototype);
sub.prototype.constructor = sub;
sub.base = base.prototype;
for(var name in methods) { sub.prototype[name] = methods[name]; }
return sub;
}
I create a class called Stimulus that serves as a function:
//In classes.js
function Stimulus(module_id, unit_id, attributes) {
this.attributes = attributes;
this.module_id = module_id;
this.unit_id = unit_id;
//create some other class variables based on this.attributes, this.module_id, and this.unit_id
}
Stimulus.prototype = {
_getStimulus: function() { //retrieve from database }
//other functions here
}
And finally I have the subclass. The technique I use to create it is also borrowed from the above link:
//In classes.js
ImageStimulus = (function() {
var $this = function(module_id, unit_id, attributes) {
$this.base.constructor.call(this, module_id, unit_id, attributes);
};
extend(Stimulus, $this, {
initialize: function() {
this.fixation_cross = this.attributes['Fixation Cross'] ? this.attributes['Fixation Cross'] : false;
//do other stuff
}
//other functions here
});
return $this;
})();
It all seems straightforward enough. However, in my main script, when I try to run this, I create the object and then try to run the initialize() function and everything falls apart:
//In main.js
var stimulus_objects = [];
for(var i = 0; i < someLimit; i++) {
//module_id is passed directly to this function
var unit_id = //some source;
var stimulus_attributes = //some source;
stimulus_objects[i] = new ImageStimulus(module_id, unit_id, stimulus_attributes);
stimulus_objects[i].initialize();
}
If I check the console I see that is says
Uncaught TypeError: Cannot read property 'Fixation Cross' of undefined
And it corresponds to the line in ImageStimulus.initialize() where I try to call on this.attributes['Fixation Cross'].
It seems that something is going wrong in making Stimulus the prototype of ImageStimulus, because ImageStimulus.initialize() cannot access the this.attributes variables that is created in the constructor for the Stimulus class.
Does anybody else see the error?
I have a decent amount of OOP programming in Java, C++, and even PHP, but this is my first attempt at JavaScript OOP, and so I feel like I'm probably making some simple mistake.
EDIT: Solved the problem... somehow.
So it seems there was a fairly trivial solution. The Stimulus function was never being called, and it should have been called on the line with $this.base.constructor.call(). In the Stimulus.prototype object I added constructor: Stimulus and now Stimulus is being called properly. It seems odd that I had to do that (shouldn't Stimulus() be it's own constructor?), but it works!
Stimulus.prototype = {
constructor: Stimulus,
_getStimulus: function() {...
Does anyone know why that occurred and why my fix worked? I'm trying to understand what I did.
I get it. You're replacing the entire prototype, so it is killing the constructor. By setting the constructor explicitly, you are putting it back. The alternative is to set the prototype method directly rather than setting the entire prototype.
For this fiddle to be useful, bring up the console and set a break point before clicking Run.
http://jsfiddle.net/x2v7wv6j/
//In functions.js
function extend(base, sub, methods) {
sub.prototype = Object.create(sub.prototype);
sub.prototype.constructor = sub;
sub.base = base.prototype;
for(var name in methods) { sub.prototype[name] = methods[name]; }
return sub;
}
//In classes.js
function Stimulus(module_id, unit_id, attributes) {
this.attributes = attributes;
this.module_id = module_id;
this.unit_id = unit_id;
//create some other class variables based on this.attributes, this.module_id, and this.unit_id
}
Stimulus.prototype._getStimulus = function() { //retrieve from database
}
//other functions here
//In classes.js
ImageStimulus = (function() {
var $this = function(module_id, unit_id, attributes) {
$this.base.constructor.call(this, module_id, unit_id, attributes);
};
extend(Stimulus, $this, {
initialize: function() {
this.fixation_cross = this.attributes['Fixation Cross'] ? this.attributes['Fixation Cross'] : false;
//do other stuff
}
//other functions here
});
return $this;
})();
var foo = function (module_id) {
var stimulus_objects = [];
var someLimit = 10;
for(var i = 0; i < someLimit; i++) {
//module_id is passed directly to this function
var unit_id = "some source";//some source;
var stimulus_attributes = "some source"; //some source;
stimulus_objects[i] = new ImageStimulus(module_id, unit_id, stimulus_attributes);
stimulus_objects[i].initialize();
}
}
foo(1);
I have a method in a base class that I want to keep in a subclass, but just add to it. I've found lots of stuff on augmenting classes and objects with properties and methods, but I can't find, or don't understand, how to just augment the method. The worst case scenario is that I would have to paste the entire method of the parent class into the subclass, but that seems like duplicate code... please help
function someObject (){
this.someProperty = 1;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
//do everything the super class has for this property already
return this.someProperty;
}
}
var incrementer = new newObject;
alert (incrementer.incrementProperty()); //I want output to be 2
// parent object
function someObject () {
this.someProperty = 1;
}
// add incrementProperty to the prototype so you're not creating a new function
// every time you instantiate the object
someObject.prototype.incrementProperty = function() {
this.someProperty += 1;
return this.someProperty;
}
// child object
function newObject () {
// we could do useful work here
}
// setup new object as a child class of someObject
newObject.prototype = new someObject();
// this allows us to use "parent" to call someObject's functions
newObject.prototype.parent = someObject.prototype;
// make sure the constructor points to the right place (not someObject)
newObject.constructor = newObject;
newObject.prototype.incrementProperty = function() {
// do everything the super class has for this property already
this.parent.incrementProperty.call(this);
return this.someProperty;
}
var incrementer = new newObject();
alert (incrementer.incrementProperty()); // I want output to be 2
See: http://jsfiddle.net/J7RhA/
this should do, you have to use prototype to have a real concept of oo with javascript
function someObject (){
this.someProperty = 1;
this.propertyOfSomeObject = 0;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
return this.propertyOfSomeObject;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
this.__super__.incrementProperty.apply(this);
return this.propertyOfSomeObject + 1;
}
}
newObject.prototype = new someObject()
newObject.prototype.__super__ = newObject.prototype
var incrementer = new newObject();
alert(incrementer.incrementProperty()); //I want output to be 2
experiment removing incrementProperty from newObject and it will return 1
I usually use the augment library to write classes in JavaScript. This is how I would rewrite your code using augment:
var Foo = Object.augment(function () {
this.constructor = function () {
this.someProperty = 1;
};
this.incrementProperty = function () {
this.someProperty++;
};
});
var Bar = Foo.augment(function (base) {
this.constructor = function () {
base.constructor.call(this);
};
this.incrementProperty = function () {
base.incrementProperty.call(this);
return this.someProperty;
};
});
As you can see since Bar extends Foo it gets Foo.prototype as a parameter (which we call base). This allows you to easily call the base class constructor and incrementProperty functions. It also shows that the constructor itself is just another method defined on the prototype.
var bar = new Bar;
alert(bar.incrementProperty());
The output will be 2 as expected. See the demo for yourself: http://jsfiddle.net/47gmQ/
From this answer:
Overriding functions
Sometimes children need to extend parent functions.
You want the 'child' (=RussionMini) to do something extra. When RussionMini can call the Hamster code to do something and then do something extra you don't need to copy and paste Hamster code to RussionMini.
In the following example we assume that a Hamster can run 3km an hour but a Russion mini can only run half as fast. We can hard code 3/2 in RussionMini but if this value were to change we have multiple places in code where it needs changing. Here is how we use Hamster.prototype to get the parent (Hamster) speed.
// from goog.inherits in closure library
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Hamster = function(name){
if(name===undefined){
throw new Error("Name cannot be undefined");
}
this.name=name;
}
Hamster.prototype.getSpeed=function(){
return 3;
}
Hamster.prototype.run=function(){
//Russionmini does not need to implement this function as
//it will do exactly the same as it does for Hamster
//But Russionmini does need to implement getSpeed as it
//won't return the same as Hamster (see later in the code)
return "I am running at " +
this.getSpeed() + "km an hour.";
}
var RussionMini=function(name){
Hamster.apply(this,arguments);
}
//call this before setting RussionMini prototypes
inherits(RussionMini,Hamster);
RussionMini.prototype.getSpeed=function(){
return Hamster.prototype
.getSpeed.call(this)/2;
}
var betty=new RussionMini("Betty");
console.log(betty.run());//=I am running at 1.5km an hour.
Considering object creation patterns with private properties, one way to do is :
function MyStack (){
var list = [],
index = 0;
this.push = function(val){
return list[index++] = val;
};
this.pop = function(){// ...}
}
var stack1 = new MyStack(); stack1.push(5);
var stack2 = new MyStack(); stack2.push(11);
Problem with this: Every instance of Stack has it's own copy of methods 'push' and 'pop'.
Another way for implementing constructor method is:
function MyStack(){
this.list = [];
this.index = 0;
}
MyStack.prototype = {
insert: function(val){
return this.list[this.index++] = val;
},
pop:function(){//...}
}
Problem here: We lose the privacy of list and index.
Is there a way, such that we can have both methods reuse among instances and privacy of properties ?
I understand that we can have this for methods that don't operate on any state of the object, but I am talking more about those methods that do operate on the state.
Yes. I've edited this code so it's actually fully functional as you had intended it to work. It seems a bit redundant to me, but, it does provide you the ability to provide a public interface, but to keep your variables private and control the way the user interacts with them.
function MyStack(){
var list = [];
var index = 0;
this.getIndex = function(){
return index;
}
this.setIndex = function(val){
index = val;
}
this.list = function(val){
if(val){
// setter if a value was provided. Illustrating how you can control
// index, which I assume is the point of having these things private
// to begin with
return list[this.setIndex(this.getIndex() + 1)] = val;
}
// always return list - acts like a getter
return list;
}
}
MyStack.prototype = {
insert: function(val){
return this.list(val);
},
pop:function(){}
}
var stack1 = new MyStack();
stack1.insert(5);
var stack2 = new MyStack();
stack2.insert(11);
You should check out John Resig's Simple Javascript Inheritance. It is a great read, and it has been extended to provide support for privates, aptly called Privates.js;
A constructor function may return any object (not necesserily this). One could create a constructor function, that returns a proxy object, that contains proxy methods to the "real" methods of the "real" instance object. This may sound complicated, but it is not; here is a code snippet:
var MyClass = function() {
var instanceObj = this;
var proxyObj = {
myPublicMethod: function() {
return instanceObj.myPublicMethod.apply(instanceObj, arguments);
}
}
return proxyObj;
};
MyClass.prototype = {
_myPrivateMethod: function() {
...
},
myPublicMethod: function() {
...
}
};
The nice thing is that the proxy creation can be automated, if we define a convention for naming the protected methods. I created a little library that does exactly this: http://idya.github.com/oolib/
I think in both approaches you mentioned, When ever object is created using constructor pattern the properties will get copied to its objects. This you mentioned for the 1st approach as the concern. I feel the same will be applied for the second approach also along with your concern in this approach.
We generally go to the second approach you mentioned when ever we want to extend the properties of "MyStack" to some other class.
Lets say i want to extend your class MyStack to MyTest like below
var dummy = function();
dummy.prototype = MyStack.prototype;
var MyTest = function(){
};
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest
var obj = new MyTest();
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();