[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.javascript

Object instance's local variable is not separate

JJ

6/7/2014 9:09:00 AM

I wanted to create a class that closely mimic the primitive type clases such
as Number, Boolean, Array, etc. I think they use a local variable to store
the value instead of a property. I got a sample code from MDN here:

<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Emulating_private_methods_with_cl...

To start with, I change it to below since it needs to be prototypal and be
an instance of the class.

function Num() {
var val = 0;
Num.prototype.changeTo= function(n) {
val = n;
};
Num.prototype.value= function() {
return val;
};
}

But the local variable seems no longer separate into each object instance as
tested below. Why is that?

n1 = new Num();
n2 = new Num();
n2.changeTo(1);
console.log(n1.value() + ", " + n2.value()); //1, 1 = fail (should be 0, 1)
console.log(n1 instanceof Num); //true = ok
console.log(Object.getPrototypeOf(n1).constructor===Num); //true = ok
5 Answers

Thomas 'PointedEars' Lahn

6/7/2014 11:48:00 AM

0

JJ <duh@nah.meh> wrote:
^^^^^^^^^^^^^^^^
<http://www.interhack.net/pubs/munging-ha.... Please fix.

> I wanted to create a class that closely mimic the primitive type clases
> such as Number, Boolean, Array, etc.

There are no classes.

<http://ecma-international.org/ecma-262/5.1/#sec...

> I think they use a local variable to store the value instead of a
> property. I got a sample code from MDN here:
>
> <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Emulating_private_methods_with_cl...
>
> To start with, I change it to below since it needs to be prototypal and be
> an instance of the class.
>
> function Num() {
> var val = 0;
> Num.prototype.changeTo= function(n) {
> val = n;
> };
> Num.prototype.value= function() {
> return val;
> };
> }

Your change has b0rked the functionality of the original code.

> But the local variable seems no longer separate into each object instance
> as tested below. Why is that?
>
> n1 = new Num();
> n2 = new Num();

After this constructor call, â??valâ? in Num.prototype.value is bound to the
local variable in the context of *that* call.

> n2.changeTo(1);

This changes *that* variable.

> console.log(n1.value() + ", " + n2.value()); //1, 1 = fail (should be 0,

And both calls return the value of *that* variable, because both objects
have the *same* object referred to by Num.prototype next in their prototype
chain.

A property can only have one value, in this case one reference to a Function
instance. Property values are resolved at runtime, through the prototype
chain if necessary.

> 1) console.log(n1 instanceof Num); //true = ok
> console.log(Object.getPrototypeOf(n1).constructor===Num); //true = ok

It has to be

function Num ()
{
var val = 0;

this.changeTo = function(n) {
val = n;
};

this.value = function() {
return val;
};
}

if objects should not share their property value, and should be something
similar to

function Num (value)
{
var _value = 0;

this.setValue = function (n) {
_value = +n;
};

this.getValue = function () {
return _value;
};

if (typeof Object.defineProperty == "function")
{
Object.defineProperty(this, "value", {
set: this.setValue
get: this.getValue,
});
}

if (arguments.length > 0)
{
this.setValue(value);
}
}

--
PointedEars
FAQ: <http://PointedEars.... | SVN: <http://PointedEars.de...
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-...
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

John Harris

6/7/2014 2:18:00 PM

0

On Sat, 7 Jun 2014 16:08:34 +0700, JJ <duh@nah.meh> wrote:

>I wanted to create a class

Beware! The word 'class' can start furious arguments in ECMAScript
circles.


>that closely mimic the primitive type clases such
>as Number, Boolean,

If you want to mimic primitive numbers and booleans then you mustn't
make them changeable. You can change the value currently held by a
variable, but you'd better not be able to change 5 into 27 or false
into true. (Oh, look : 6 - 1 = 27). If you want a different value you
create a new value and throw away the old one.


>Array, etc.

Is an Array really primitive? Certainly an Array object isn't.


>I think they use a local variable to store
>the value instead of a property.

I very much doubt it. It's extremely unlikely to be a local var in the
code of an ECMAScript function body.

The compiler will translate
x = 42;
into machine code where the floating point number with the value 42 is
written into the value field of whatever machine data structure is
used for holding the variable. (Or if not it's going to run very
slowly.)


>I got a sample code from MDN here:
>
><https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Emulating_private_methods_with_cl...

Closures stop other people changing values that mustn't be changed, or
corrupting values that are held in a special internal format. Is
either of these applicable to general, as opposed to restricted,
primitive values?

John

JJ

6/7/2014 3:36:00 PM

0

On Sat, 07 Jun 2014 13:48:14 +0200, Thomas 'PointedEars' Lahn wrote:
> JJ <duh@nah.meh> wrote:
> ^^^^^^^^^^^^^^^^
> <http://www.interhack.net/pubs/munging-ha.... Please fix.

What are the options other than using my real email address?

> There are no classes.
>
> <http://ecma-international.org/ecma-262/5.1/#sec...

My bad.

>> n1 = new Num();
>> n2 = new Num();
>
> After this constructor call, ?val? in Num.prototype.value is bound to the
> local variable in the context of *that* call.

So, does this means there's only one "val" variable in that context?

>> 1) console.log(n1 instanceof Num); //true = ok
>> console.log(Object.getPrototypeOf(n1).constructor===Num); //true = ok
>
> It has to be
>
> function Num ()
> {
> var val = 0;
>
> this.changeTo = function(n) {
> val = n;
> };
>
> this.value = function() {
> return val;
> };
> }

What about the prototypal Number object, where:

(new Number()).toFixed === Number.prototype.toFixed

How to implement that?

Thomas 'PointedEars' Lahn

6/7/2014 7:03:00 PM

0

JJ wrote:

> On Sat, 07 Jun 2014 13:48:14 +0200, Thomas 'PointedEars' Lahn wrote:
>> JJ <duh@nah.meh> wrote:
>> ^^^^^^^^^^^^^^^^
>> <http://www.interhack.net/pubs/munging-ha.... Please fix.
>
> What are the options other than using my real email address?

Your reasonable options are discussed in that document.

I recommend to use the address of an aggressively-filtered, seldom-read (but
*read*) mailbox for the From header field, and the address of a more often
read mailbox for the Reply-To header field. That is what I do.

>>> n1 = new Num();
>>> n2 = new Num();
>>
>> After this constructor call, â??valâ? in Num.prototype.value is bound to the
>> local variable in the context of *that* call.
>
> So, does this means there's only one "val" variable in that context?

There is only one â??valâ? variable per execution context. However, the point
here is that by overwriting the prototypeâ??s property value in the
constructor you are binding the identifier reference in the prototype method
always to *that* variable, i. e. that of the execution context of the last
constructor call.

>>> 1) console.log(n1 instanceof Num); //true = ok
>>> console.log(Object.getPrototypeOf(n1).constructor===Num); //true = ok
>>
>> It has to be
>>
>> function Num ()
>> {
>> var val = 0;
>>
>> this.changeTo = function(n) {
>> val = n;
>> };
>>
>> this.value = function() {
>> return val;
>> };
>> }
>
> What about the prototypal Number object, where:
>
> (new Number()).toFixed === Number.prototype.toFixed
>
> How to implement that?

The expression evaluates to true because the left-hand side is resolved
to Number.prototype.toFixed through the prototype chain.

("toFixed" in (new Number())) === true

but

(new Number()).hasOwnProperty("toFixed") === false

(Besides, new Number(â?¦) should be avoided.)

As for exactly the same functionality as the built-in object, I do not think
that is possible. A user-defined prototype method needs a publicly
accessible property on the instance. You could only have a public prototype
method calling a "privileged" instance method which accesses the context-
local variable aka the "private property". The following comes close:

"use strict";

Object.defineProperty(this, "Num", {
configurable: true,
/* not enumerable */
writable: true,

value: function Num (value) {
var has_args = (arguments.length > 0);

if (!(this instanceof Num))
{
if (has_args)
{
return +value;
}

return 0;
}

var _primitive_value = (has_args ? +value : 0);

Object.defineProperty(this, "_getPrimitiveValue", {
/* not configurable, not enumerable, not writable */

value: function () {
return _primitive_value;
}
});
}
});

Object.defineProperty(this.Num, "prototype", {
/* not configurable, not enumerable, not writable */

value: (function (_global) {
var prototype = new _global.Num();

Object.defineProperties(prototype, {
/* â?¦ */

toFixed: {
configurable: true,
writable: true,

value: function (precision) {
var primitive_value = this._getPrimitiveValue();

/* achieve precision */

return primitive_value;
}
},

toString: {
configurable: true,
writable: true,

value: function (radix) {
return this._getPrimitiveValue().toString(radix);
}
},

valueOf: {
configurable: true,
writable: true,

value: function () {
return this._getPrimitiveValue();
}
}
});

return prototype;
}(this))
});

See also <http://ecma-international.org/ecma-262/5.1/#se....

--
PointedEars
FAQ: <http://PointedEars.... | SVN: <http://PointedEars.de...
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-...
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

JJ

6/9/2014 1:18:00 AM

0

On Sat, 07 Jun 2014 21:03:17 +0200, Thomas 'PointedEars' Lahn wrote:
>
> Your reasonable options are discussed in that document.
>
> I recommend to use the address of an aggressively-filtered, seldom-read (but
> *read*) mailbox for the From header field, and the address of a more often
> read mailbox for the Reply-To header field. That is what I do.

OK, thanks.

> As for exactly the same functionality as the built-in object, I do not think
> that is possible. A user-defined prototype method needs a publicly
> accessible property on the instance. You could only have a public prototype
> method calling a "privileged" instance method which accesses the context-
> local variable aka the "private property". The following comes close:
[snip]

Bummer.

> See also <http://ecma-international.org/ecma-262/5.1/#se....

Will definitely do. Thanks again.