javascript. References problems. Inheritance. Scope This - javascript

Look my problem:
I have a class that look like this:
var els=[];
var base = function(){
this.config = {}
}
var X1 = function(){
}
X1.prototype = new base();
X1.prototype.indexme = function(i){
this.config.index = i;
}
X1.prototype.add = function(){
var i = els.push(this)
this.indexme(i)
}
var teste = new X1();
teste.add();
var teste2 = new X1();
teste2.add();
var teste3 = new X1();
teste3.add();
console.log(els)
Why this.config.index is overwritten to another instances?
I expected that teste have config.index = 1; teste2 config.index= 2 and teste3 config.index=3
Thanks

All instances of X1 share the same prototype, which is an instance of base with a config property. Thus, all instances of X1 share the same config property. You can move the line this.config = {}; to the X1 constructor or you can define an init() function in base that assigns this.config for each object and call init() from the X1 constructor.

Related

javascript new does not create new object

I am trying to get two objects from the same class definition. However they seem to share the same attribute. What can i do?
http://jsfiddle.net/dagod/nuam8dks/2/
myclass = function() {
this.data.push(Math.random(1000));
};
myclass.prototype.data = [];
a = new myclass();
b = new myclass();
console.log(a.data);
console.log(b.data); //same as a.data
I've just been doing this for something else!
myclass = function() {
this.data = [];
};
Now you can access it my simply doing myclass.data =
Personally this is how i'd do it:
var MyNameSpace = {
SomeFunction: function() {
Some code
};
this.somevariable = somevalue;
};
Then you can go myNameSpace.myfunction() or myNameSpace.myVar = Value
See the comment from elclanrs.
var Myclass = function() {
this.data = [];
this.data.push(Math.random(1000));
};
You need to declare your member variable inside the constructor instead of making them part of the prototype. oop in javascript can be ugly and unintuitive. (Thats why there are so many oop libraries out there for javascript)
Using ds.oop
ds.make.class({
type: 'MyClass',
constructor: function(x){
this.a = x;
}
});
var c1 = new MyClass(1);
var c2 = new MyClass(2);
console.log( c1.a ); // output: 1
console.log( c2.a ); // output: 2
You can get the desired results as follows:
myclass = function() {
this.data = Math.random(1000);
};
//myclass.prototype.data = [];
var a = new myclass();
var b = new myclass();
jsfiddle

call javascript object function

I have two objects of the same type.
function myObject(){
this.a = 1;
this.b = 1;
function changeA(){//some code};
function changeB(){//some code};
}
var obj1 = new myObject();
var obj2 = new myObject();
How can I make a call to obj2.changeB() from external code, another function or another object (e.g. obj1) ?
obj2.changeB() doesn't exist.
You need to assign a property on your object, not create a local variable:
this.changeB = function() { ... };
Just create a properties in you object like:
function myObject(){
this.a = 1;
this.b = 1;
this.functionA = function changeA(){//some code
alert('im 1');
};
this.functionb = function changeB(){//some code
alert('im 2');};
}
and call the function obj2.functionb();
LIVE DEMO
You have to do something like that:
var myObject = function(){
var protectedValue1 = ‘variable’;
var protectedValue2 = ‘variable’;
var changeA = function(){
alert(protectedValue);
}
var changeB = function(){
alert(protectedValue);
}
}
var object1 = new myObject();
var object2 = new myObject();
//
object2.changeB();

multi inherit or access the property and method outside the object

var ob = function(){
};
ob.prototype.func = function(){
};
var t = function(){
this.p=0;
this.function1(){
}
var a=new ob();
a.func=function(){//overrides the func
//hope to access this.p this.function1
}
};
is it possible to make a can access this.p this.function1 ?
Your comment welcome
You need to keep a reference to this from inside t if you want to access it within a.func. Try the following:
var t = function(){
var this_t = this; // Use this_t to access this.p and this.function1 inside a
this.p=0;
this.function1 = function(){
}
var a=new ob();
a.func = function(){//overrides the func
this_t.p = 1;
this_t.function1();
}
};

Cloned objects and reference inside functions

I am trying to do the following:
var element = {};
element.attrA = 'A';
element.attrB = 1;
element.autoAdvance = function(){
var that = this;
setInterval(function(){
that.attrB++;
},100);
}
element.instance = function(){
var clone = $.extend(true, {}, this);
return clone;
}
Now I can do the following just fine:
var e1 = element.instance();
var e2 = element.instance();
e1.attrA = 'not e2s business';
e2.attrA = 'not e1s attrA';
The trouble starts when I try to use autoAdvance:
e1.autoAdvance();
will start the autoAdvance for all cloned 'instances' of element. I am sure this is probably rather trivial but I just don't know how to refer to the parent object inside my autoAdvance-function in a way that it gets properly cloned and only affects the instance. Thanks!
EDIT:
This is the actual code I am using:
var player = {};
player.sprites = {};
player.sprites.back = ['img/playerback_01.png','img/playerback_02.png','img/playerback_03.png'];
player.sprites.head = ['img/playerhead_01.png','img/playerhead_02.png','img/playerhead_03.png'];
player.back = new Image();
player.back.src = player.sprites.back[0];
player.head = new Image();
player.head.src = player.sprites.head[0];
player.loop = function(){
var that = this;
var loop = setInterval(function(){
//remove the [0] state from the sprite array and add it at [2]
var state = that.sprites.head.shift();
that.sprites.head.push(state);
state = that.sprites.back.shift();
that.sprites.back.push(state);
that.back.src = that.sprites.back[0];
that.head.src = that.sprites.head[0];
}, 100);
}
player.x = 0;
player.y = 0;
player.instance = function(){
var clone = $.extend(true, {}, this);
return clone;
}
I generate two players:
var player1 = player.instance();
var player2 = player.instance();
But what is happening is that when I use:
player1.loop();
The animation for player2 will start to play as well.
I suggest you start using "class" in JavaScript. They are more or less a function.
function Player(){
this.sprites={};
......
}
Player.prototype.loop=function(){
....
}
var player1=new Player();
var player2=new Player();
player1.loop();
player2.loop();// this should work better
It doesn't really answer your question but it's an alternative way to write code in a cleaner and better way.

Javascript "private" vs. instance properties

I'm doing some Javascript R&D and, while I've read Javascript: The Definitive Guide and Javascript Object Oriented Programming, I'm still having minor issues getting my head out of class based OOP and into lexical, object based OOP.
I love modules. Namespaces, subclasses and interfaces. w00t. Here's what I'm playing with:
var Classes = {
_proto : {
whatAreYou : function(){
return this.name;
}
},
Globe : function(){
this.name = "Globe"
},
Umbrella : new function(){
this.name = "Umbrella"
}(),
Igloo : function(){
function Igloo(madeOf){
this.name = "Igloo"
_material = madeOf;
}
// Igloo specific
Igloo.prototype = {
getMaterial : function(){
return _material;
}
}
// the rest
for(var p in Classes._proto){
Igloo.prototype[p] = Classes._proto[p]
}
return new Igloo(arguments[0]);
},
House : function(){
function House(){
this.name = "My House"
}
House.prototype = Classes._proto
return new House()
}
}
Classes.Globe.prototype = Classes._proto
Classes.Umbrella.prototype = Classes._proto
$(document).ready(function(){
var globe, umb, igloo, house;
globe = new Classes.Globe();
umb = Classes.Umbrella;
igloo = new Classes.Igloo("Ice");
house = new Classes.House();
var objects = [globe, umb, igloo, house]
for(var i = 0, len = objects.length; i < len; i++){
var me = objects[i];
if("whatAreYou" in me){
console.log(me.whatAreYou())
}else{
console.warn("unavailable")
}
}
})
Im trying to find the best way to modularize my code (and understand prototyping) and separate everything out. Notice Globe is a function that needs to be instantiated with new, Umbrella is a singleton and already declared, Igloo uses something I thought about at work today, and seems to be working as well as I'd hoped, and House is another Iglooesque function for testing.
The output of this is:
Globe
unavailable
Igloo
My House
So far so good. The Globe prototype has to be declared outside the Classes object for syntax reasons, Umbrella can't accept due to it already existing (or instantiated or... dunno the "right" term for this one), and Igloo has some closure that declares it for you.
HOWEVER...
If I were to change it to:
var Classes = {
_proto : {
whatAreYou : function(){
return _name;
}
},
Globe : function(){
_name = "Globe"
},
Umbrella : new function(){
_name = "Umbrella"
}(),
Igloo : function(){
function Igloo(madeOf){
_name = "Igloo"
_material = madeOf;
}
// Igloo specific
Igloo.prototype = {
getMaterial : function(){
return _material;
}
}
// the rest
for(var p in Classes._proto){
Igloo.prototype[p] = Classes._proto[p]
}
return new Igloo(arguments[0]);
},
House : function(){
function House(){
_name = "My House"
}
House.prototype = Classes._proto
return new House()
}
}
Classes.Globe.prototype = Classes._proto
Classes.Umbrella.prototype = Classes._proto
$(document).ready(function(){
var globe, umb, igloo, house;
globe = new Classes.Globe();
umb = Classes.Umbrella;
igloo = new Classes.Igloo("Ice");
house = new Classes.House();
var objects = [globe, umb, igloo, house]
for(var i = 0, len = objects.length; i < len; i++){
var me = objects[i];
if("whatAreYou" in me){
console.log(me.whatAreYou())
}else{
console.warn("unavailable")
}
}
})
and make this.name into _name (the "private" property), it doesn't work, and instead outputs:
My House
unavailable
My House
My House
Would someone be kind enough to explain this one? Obviously _name is being overwritted upon each iteration and not reading the object's property of which it's attached.
This all seems a little too verbose needing this and kinda weird IMO.
Thanks :)
You declare a global variable. It is available from anywhere in your code after declaration of this. Wherever you request to _name(more closely window._name) you will receive every time a global. In your case was replaced _name in each function. Last function is House and there has been set to "My House"
Declaration of "private" (local) variables must be with var statement.
Check this out:
var foo = function( a ) {
_bar = a;
this.showBar = function() {
console.log( _bar );
}
};
var a = new foo(4); // _bar ( ie window._bar) is set to 4
a.showBar(); //4
var b = new foo(1); // _bar is set to 1
a.showBar(); //1
b.showBar(); //1
_bar = 5; // window._bar = 5;
a.showBar();// 5
Should be:
var foo = function( a ) {
var _bar = a;
// _bar is now visibled only from both that function
// and functions that will create or delegate from this function,
this.showBar = function() {
console.log( _bar );
};
this.setBar = function( val ) {
_bar = val;
};
this.delegateShowBar = function() {
return function( ) {
console.log( _bar );
}
}
};
foo.prototype.whatever = function( ){
//Remember - here don't have access to _bar
};
var a = new foo(4);
a.showBar(); //4
_bar // ReferenceError: _bar is not defined :)
var b = new foo(1);
a.showBar(); //4
b.showBar(); //1
delegatedShowBar = a.delegateShowBar();
a.setBar(6);
a.showBar();//6
delegatedShowBar(); // 6
If you remove the key word "this", then the _name is in the "Globe" scope.
Looking at your code.
var globe, umb, igloo, house;
globe = new Classes.Globe();
umb = Classes.Umbrella;
igloo = new Classes.Igloo("Ice");
house = new Classes.House();
At last the house will override the "_name" value in globe scope with the name of "My House".

Categories