Very strange problem with Class object

P

Piotr K

I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:

var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};
}

var X = new Class({
arr: []
});

var x = new X;
x.arr.push(5);

var y = new X;
alert(y.arr[0]) // displays 5

How, I mean HOW in the world it displays 5? I tested it with normal
string and number variables - works fine, but I can't figure what's
wrong with the arrays? I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..

Thanks for any help!
 
V

VK

I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:

var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};

}

var X = new Class({
arr: []

});

var x = new X;
x.arr.push(5);

var y = new X;
alert(y.arr[0]) // displays 5

How, I mean HOW in the world it displays 5? I tested it with normal
string and number variables - works fine, but I can't figure what's
wrong with the arrays? I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..

Because you have created a very efficient memory leak over closure
with tpl value retained in it. I honestly have no idea what does this
code suppose to mean. Is it some work-on-denial test for a script
engine? There are more sophisticated professional packages for that,
Acid 3 from the first coming into my mind.
 
P

Piotr K

I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:
var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};

var X = new Class({
arr: []

var x = new X;
x.arr.push(5);
var y = new X;
alert(y.arr[0]) // displays 5
How, I mean HOW in the world it displays 5? I tested it with normal
string and number variables - works fine, but I can't figure what's
wrong with the arrays? I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..

Because you have created a very efficient memory leak over closure
with tpl value retained in it. I honestly have no idea what does this
code suppose to mean. Is it some work-on-denial test for a script
engine? There are more sophisticated professional packages for that,
Acid 3 from the first coming into my mind.

It creates classes, the same way that ie. mooTools does, I just
shortened it for clarity.. however, I managed to solve my problem ;)
btw. mooTools Class suffers from the same problem which kind a
suprised me
 
V

VK

I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:
var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};
}
var X = new Class({
arr: []
});
var x = new X;
x.arr.push(5);
var y = new X;
alert(y.arr[0]) // displays 5
How, I mean HOW in the world it displays 5? I tested it with normal
string and number variables - works fine, but I can't figure what's
wrong with the arrays? I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..
Because you have created a very efficient memory leak over closure
with tpl value retained in it. I honestly have no idea what does this
code suppose to mean. Is it some work-on-denial test for a script
engine? There are more sophisticated professional packages for that,
Acid 3 from the first coming into my mind.

It creates classes, the same way that ie. mooTools does, I just
shortened it for clarity.. however, I managed to solve my problem ;)

You did? OK, enjoy your program working with a memory monitor.
btw. mooTools Class suffers from the same problem which kind a
suprised me.

You mean mooTools cut a deal with the Spirit of Programming so memory
leaks and closures should not be applicable to it no matter how bad
the code is? :) :-|

My heart is bleeding by looking at this code. Maybe you could take
Prototype.js and its pattern instead? It still imitating class-based
paradigm but it has some respect to the real nature of the used
language so it does not leak 1Mb per 50Kb of code.

Up to you, anyway.
 
P

Piotr K

I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:
var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};
}
var X = new Class({
arr: []
});
var x = new X;
x.arr.push(5);
var y = new X;
alert(y.arr[0]) // displays 5
How, I mean HOW in the world it displays 5? I tested it with normal
string and number variables - works fine, but I can't figure what's
wrong with the arrays? I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..
Because you have created a very efficient memory leak over closure
with tpl value retained in it. I honestly have no idea what does this
code suppose to mean. Is it some work-on-denial test for a script
engine? There are more sophisticated professional packages for that,
Acid 3 from the first coming into my mind.
It creates classes, the same way that ie. mooTools does, I just
shortened it for clarity.. however, I managed to solve my problem ;)

You did? OK, enjoy your program working with a memory monitor.
btw. mooTools Class suffers from the same problem which kind a
suprised me.

You mean mooTools cut a deal with the Spirit of Programming so memory
leaks and closures should not be applicable to it no matter how bad
the code is? :) :-|

My heart is bleeding by looking at this code. Maybe you could take
Prototype.js and its pattern instead? It still imitating class-based
paradigm but it has some respect to the real nature of the used
language so it does not leak 1Mb per 50Kb of code.

Up to you, anyway.

Ups, my mistake, they made it a little diffrent - rather than coping
all attributes they assign them to returned function prototype. So
after change the Class look like this:

var Class = function(tpl) {
var f = function() {
}

f.prototype = tpl;
f.constructor = Class;
return f;
}

I guess this is memory-leek free? :)
 
R

Richard Cornford

Piotr said:
I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:

var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};
}

var X = new Class({
arr: []
});

var x = new X;
x.arr.push(5);

var y = new X;
alert(y.arr[0]) // displays 5

How, I mean HOW in the world it displays 5?

You assign a reference to an array to its 'arr' property when your
create your - x - object and then assign a reference to the same array
to the 'arr' property of your - y - object when your create that. Then
when you push an element onto that array it is a member of the array
referred to as - x.arr - and - y.arr -.
I tested it with normal
string and number variables - works fine,

Using - push - on an array is modifying that array. There are no
operations in javascript that are capable of modifying a primitive
value, so you could not be doing the equivalent to a string or a number.
but I can't figure what's wrong with the arrays?

What is wrong is that you are expecting each object instance to have its
own array instance but you have programmed them to share a single array
instance.
I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..

function X(){
this.arr = [];
}

var x = new X;
x.arr.push(5);

var y = new X;
alert(y.arr[0]) // displays undefined

Don't over-complicate things.
Thanks for any help!

It is best to disregard anything that VK says as he has no idea what his
own cod actually does let alone anyone else's. Earlier in the week he
posted:-

| <script type="text/javascript">
| (function(){
| var name = 'doc02';
| document.write(''.concat(
| '<iframe name="',name,'" ',
| 'src="',getUrlForIframe(name),'" ',
| 'onload="',
| '(function(){',
| 'var n = \'',name,'\';',
| 'var win = self.frames[n];',
| 'var doc = win.document;',
| 'if ((doc) && (\'designMode\' in doc)) {',
| ' doc.designMode = \'on\';',
| '}','})();"'));
| window.alert('Fine up to this point');
| })();
| window.alert('getUrlForIframe is ' + typeof getUrlForIframe);
| window.setTimeout('window.alert(true)',1000);
| </script>

- which is insane, and if you asked him to explain that - onload -
attribute he either could not or would post a nonsense explanation.

Richard.
 
T

Thomas 'PointedEars' Lahn

Piotr said:
It creates classes,

It does not. It cannot, since current client-side implementations do not
support classes but use prototype-based inheritance instead. The sooner you
understand this, the sooner you are running the chance of writing efficient
and easily maintainable ECMAScript-compliant programs.
the same way that ie. mooTools does,

Bad (and worse) code written by other clueless people does not justify bad
code on your part. It is that fundamental design flaw that makes many
client-side script libraries useless in a wider Web context, especially in
conjunction with other libraries; particularly MooTools here because it
follows several of the mindboggingly stupid design patterns of the
Prototype.js junk.

You will be best off ignoring VK, the resident fairytale-teller, when it
comes to any sort of technical advice; or you should take everything they
say with a handful (two? a box?) of salt.


PointedEars
 
L

Lasse Reichstein Nielsen

Piotr K said:
Ups, my mistake, they made it a little diffrent - rather than coping
all attributes they assign them to returned function prototype. So
after change the Class look like this:

var Class = function(tpl) {
var f = function() {
}

f.prototype = tpl;
f.constructor = Class;

This line doesn't really do anything (unless the rest of the library
it is contained in uses the constructor property).
I would expect the following instead:
tpl.constructor = f;
return f;
}

The will still have the same problem as your original program:
var myClass = Class({arr:[]});
var x = new myClass();
var y = new myClass();
will share the same array instance as x.arr and y.arr. You only ever
create one array (the "[]" array literal), so the instances will have
to share.
I guess this is memory-leek free? :)

I have no idea what memory leak we are talking about. The original
version had no memory leak that I could see.

/L
 
V

VK

I simply ran out of ideas why this piece of code works so strange,
it's a very simple class creating object:
var Class = function(tpl) {
return function() {
for(var t in tpl) this[t] = tpl[t];
};
}
var X = new Class({
arr: []
});
var x = new X;
x.arr.push(5);
var y = new X;
alert(y.arr[0]) // displays 5
How, I mean HOW in the world it displays 5? I tested it with normal
string and number variables - works fine, but I can't figure what's
wrong with the arrays? I tried to change the Class function in many
ways like making "new Object(tpl[t])" or "tpl[t].valueOf()" but
nothing helped.. I'm frustrated, it's so freakin strange..
Because you have created a very efficient memory leak over closure
with tpl value retained in it. I honestly have no idea what does this
code suppose to mean. Is it some work-on-denial test for a script
engine? There are more sophisticated professional packages for that,
Acid 3 from the first coming into my mind.

Maybe I should be more detailed. What you have originally posted is a
version of mutable anonymous constructor. This sick invention of some
Perl OOP traumatized programmer got in big fashion last year for some
reason: lucky by now this madness gets lesser and lesser popular. Do
do not be distracted by side issues, let's us take a mutable anonymous
constructor in its most simple form (comments are below the HTML):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en-US">
<head>
<meta http-equiv="Content-type"
content="text/html; charset=iso-8859-1">
<title>Demo</title>
<script type="text/javascript">

function Parent(outer_arg) {
return function(inner_arg) {
this['foo'] = outer_arg;
this['bar'] = inner_arg;
}
}

var Child = new Parent('foo');

var a = new Child('bar_a');

var b = new Child('bar_b');

var c = new Child('bar_c');

window.alert(a.foo==b.foo && b.foo==c.foo && c.foo=='foo'); // true

window.alert(a.bar); // 'bar_a'

window.alert(b.bar); // 'bar_b'

window.alert(c.bar); // 'bar_c'

</script>
</head>
<body>
<p>No content</p>
</body>
</html>

So what we have got here:

1) Parent creates Child and provides closure for Child. Grace to it on
each call Child has access to Parent context including outer_arg. This
is where in your sample the "mysterious" 5 value comes out.
2) Child constructor creates instances with per-instance properties.
Because Parent and Child are neither in class nor prototype
inheritance relations, I would say that 2007 was the year of birth of
all new "closure-based inheritance".
Once I tried to get an answer from one CS specialist what all these
mutable anonymous constructors - or closure-based inheritance or name
it as you want - is good for. With a light in he eyes he explained
that it allows to get all different instances from the same class
which are not in OOP relations with each other. Maybe I did not get
him right, or maybe he already got too much of Californian sun, or I
did, or both us. Any way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top