# Math ugliness.

Discussion in 'Javascript' started by Jorge, Feb 16, 2010.

1. ### JorgeGuest

Hi,

Do you think -as I do- that the Math object is an ugly artifact ?
Well, here's a nice way of getting rid of it :

Number.prototype.sin= function () { return Math.sin(+this); };
Number.prototype.asin= function () { return Math.asin(+this); };
Number.prototype.pow= function (p) { return Math.pow(+this, p); };
Number.prototype.sqrt= function () { return Math.sqrt(+this); };
Number.prototype.rnd= function () { return this*Math.random(); }

etc..

x= 16;
x.sqrt()
--> 4

x="256";
(+x).pow(2) //be sure to call the right .proto
--> 65536

(1.234).sin().asin()
--> 1.234

1..asin() * 2
-> 3.141592653589793

(2).pow(10)
--> 1024

2..pow(10).sqrt()
--> 32

(100).rnd()
-> 0 <= n < 100
--
Jorge.

Jorge, Feb 16, 2010

2. ### Cody HainesGuest

Jorge <> wrote:
> Hi,
>
> Do you think -as I do- that the Math object is an ugly artifact ?
> Well, here's a nice way of getting rid of it :
>
> Number.prototype.sin= function () { return Math.sin(+this); };
> Number.prototype.asin= function () { return Math.asin(+this); };
> Number.prototype.pow= function (p) { return Math.pow(+this, p); };
> Number.prototype.sqrt= function () { return Math.sqrt(+this); };
> Number.prototype.rnd= function () { return this*Math.random(); }
>
> etc..
>
> x= 16;
> x.sqrt()
> --> 4
>
> x="256";
> (+x).pow(2) //be sure to call the right .proto
> --> 65536
>
> (1.234).sin().asin()
> --> 1.234
>
> 1..asin() * 2
> -> 3.141592653589793
>
> (2).pow(10)
> --> 1024
>
> 2..pow(10).sqrt()
> --> 32
>
> (100).rnd()
> -> 0 <= n < 100
> --
> Jorge.
>

Just out of curiosity, does IE support this? I don't see why it
wouldn't, just making sure

--
--Cody Haines

Cody Haines, Feb 17, 2010

3. ### RobGGuest

On Feb 17, 9:23 am, Jorge <> wrote:
> Hi,
>
> Do you think -as I do- that the Math object is an ugly artifact ?
> Well, here's a nice way of getting rid of it :
>
> Number.prototype.sin= function () { return Math.sin(+this); };

I'm curious about the use of unary +. Presumably the identifier is
resolved to a number primitive in the first place, otherwise x.sin
wouldn't resolve to Number.prototype.sin.

Or have I missed something?

[...]
> x="256";
> (+x).pow(2) //be sure to call the right .proto
> --> 65536

So if x must be a number in order for the right property to be found,
why must it also be converted inside the function?

--
Rob

RobG, Feb 17, 2010
4. ### Thomas 'PointedEars' LahnGuest

Cody Haines wrote:

> Jorge <> wrote:
>> Do you think -as I do- that the Math object is an ugly artifact ?
>> Well, here's a nice way of getting rid of it :
>>
>> Number.prototype.sin= function () { return Math.sin(+this); };
>> Number.prototype.asin= function () { return Math.asin(+this); };
>> Number.prototype.pow= function (p) { return Math.pow(+this, p); };
>> Number.prototype.sqrt= function () { return Math.sqrt(+this); };
>> Number.prototype.rnd= function () { return this*Math.random(); }
>>
>> etc..
>>
>> x= 16;
>> x.sqrt()
>> --> 4
>>
>> x="256";
>> (+x).pow(2) //be sure to call the right .proto
>> --> 65536
>>
>> (1.234).sin().asin()
>> --> 1.234
>>
>> 1..asin() * 2
>> -> 3.141592653589793
>>
>> (2).pow(10)
>> --> 1024
>>
>> 2..pow(10).sqrt()
>> --> 32
>>
>> (100).rnd()
>> -> 0 <= n < 100
>> [...]

>
> Just out of curiosity, does IE support this? I don't see why it
> wouldn't, just making sure

JScript 5.6.6626 as of IE 6.0.2800.1106 supports this. It stands to reason
that later versions of JScript and Internet Explorer, therefore other
MSHTML-based browsers, would also support this (I cannot test them here
yet).

In fact, given that, according to Editions 3 and 5 of the ECMAScript
Language Specification, when evaluating the CallExpression's
/MemberExpression/ any primitive value would be converted into an
appropriate value of type Object (ES3/5, 11.2.3, 11.2.1, and 9.9), this
SHOULD work everywhere where `Number.prototype' is supported (which AFAIK
excludes only JavaScript 1.0 as of Netscape 2.x, and JScript 1.0 as of IE
3.0 and IIS 3.0 ).Â¹ Tests with JavaScript, Apple JSC, Opera ECMAScript,
and KJS confirmed this a while ago; I could also confirm it for Google V8
2.0 as of Chrome 5.0.307.7 by now. (In fact, this idea is anything but
original.)

However, the better question is: Does it make sense to do this?

You could lose the explicit type conversion to begin with (as it is done
implicitly by the algorithms of the built-in methods of `Math'; see ES3/5,
15.8.2).

Still, with regard to memory efficiency your stack would be one level
higher than without it, and with regard to runtime efficiency you would be
paying for one call more than without it. Stack space being a scarce
resource, and calls being rather expensive, this approach does not appear
to make much sense.

PointedEars
___________
Â¹ To be sure of that, I have debugged the algorithms of ECMAScript Ed. 5,
and compared with Ed. 3; I can post more detailed results of my
research if anyone is interested.
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Thomas 'PointedEars' Lahn, Feb 17, 2010
5. ### Thomas 'PointedEars' LahnGuest

kangax wrote:

> RobG wrote:
>> Jorge wrote:
>>> Do you think -as I do- that the Math object is an ugly artifact ?
>>> Well, here's a nice way of getting rid of it :
>>>
>>> Number.prototype.sin= function () { return Math.sin(+this); };

>>
>> I'm curious about the use of unary +. Presumably the identifier is
>> resolved to a number primitive in the first place, otherwise x.sin
>> wouldn't resolve to Number.prototype.sin.

>
>
> I'm guessing ToNumber conversion is there to make method intentionally
> generic, similar to, say, `String.prototype.trim` from ES5, which passes
> its this value through ToString before trimming a value.

It is still superfluous as the methods of `Math' already call ToNumber() on
each of their arguments.

PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at\$ail\$1\$>

Thomas 'PointedEars' Lahn, Feb 17, 2010
6. ### JorgeGuest

On Feb 17, 4:10 am, RobG <> wrote:
> On Feb 17, 9:23 am, Jorge <> wrote:
>
> > Hi,

>
> > Do you think -as I do- that the Math object is an ugly artifact ?
> > Well, here's a nice way of getting rid of it :

>
> > Number.prototype.sin= function () { return Math.sin(+this); };

>
> I'm curious about the use of unary +. Presumably the identifier is
> resolved to a number primitive in the first place, otherwise x.sin
> wouldn't resolve to Number.prototype.sin.
>
> Or have I missed something?

I believe it gets -automatically- wrapped in an object just before -in
order to do- the property lookup... ¿?

> [...]
>
> > x="256";
> > (+x).pow(2) //be sure to call the right .proto
> > --> 65536

>
> So if x must be a number in order for the right property to be found,
> why must it also be converted inside the function?

I did that because I recall that new Number(3) !== new Number(3): IOW,
because "this" is -supposedly- an object.

This idea occurred to me yesterday late at night while watching
Crockford on JS video #2, and I just posted it here on the fly without
--
Jorge.

Jorge, Feb 17, 2010
7. ### JorgeGuest

On Feb 17, 6:14 am, Thomas 'PointedEars' Lahn <>
wrote:
>
> (...) In fact, this idea is anything but original. (...)

And then came Pointy, decided to spoil the fun...

I've never seen it before.. who, where, when ? Have you got any urls,
plz ?
--
Jorge.

Jorge, Feb 17, 2010
8. ### Dmitry A. SoshnikovGuest

On Feb 17, 2:23 am, Jorge <> wrote:
> Hi,
>
> Do you think -as I do- that the Math object is an ugly artifact ?
> Well, here's a nice way of getting rid of it :
>

Artifact of not - that's questionable, because some methods fit to
numbers (e.g. .round(), other), some by semantic - for mathematical
actions and could be placed in separate Math'ematical module.

Other question is style of code. I always don't like to repeat some
chunks of code, I always try to decrease such repetitions. That's why
I really don't like new approach in ES5 for methods to work with
objects which are placed not in `Object.prototype' letting to work in
OOP-style, but in `Object' constructor itself. I know the reasons why
it was done so (such a "protection" if simple object will have own
such property), but that seems to my ugly too (just an abstract
example):

var o = Object.freeze(
Object.seel(
Object.defineProperties(
Object.create(proto),
properties
)
)
);

This repetition of Object.-Object.-Object. is really `heavy'. The
first thing which also can be done in ES5 (to make it more comfortable
in some viewpoint) - is definition of the same methods in
`Object.prototype' (with [[Enumerable]] = false), allowing elegant
chains, decreasing of the repeated chunks of code such as `Object.':

var o = Object.create(proto)
.defineProperties(properties)
.seel()
.freeze();

By the way, e.g. in Ruby, many of this methods (and for numbers and
for objects) are instance methods:

1.5.round()
{'a' => 10}.freeze()

and so on.

/ds

Dmitry A. Soshnikov, Feb 17, 2010
9. ### JorgeGuest

On Feb 17, 10:15 am, "Dmitry A. Soshnikov"
<> wrote:
>
> By the way, e.g. in Ruby, many of this methods (and for numbers and
> for objects) are instance methods:
>
> 1.5.round()
> {'a' => 10}.freeze()
>
> and so on.

That's the way it ought to be, imo, and JS is powerful enough that
allows for sculpting it at your liking.
--
Jorge.

Jorge, Feb 17, 2010
10. ### JorgeGuest

On Feb 17, 10:33 am, "Richard Cornford" <>
wrote:
>
> - implies two numeric primitive to Number object type-conversations

One sometimes has to wonder what's really going on inside one's
browser... "primitive" "conversations" ? LOL.
--
Jorge.

Jorge, Feb 17, 2010
11. ### JorgeGuest

On Feb 17, 10:15 am, "Dmitry A. Soshnikov"
<> wrote:
> On Feb 17, 2:23 am, Jorge <> wrote:
>
> > Hi,

>
> > Do you think -as I do- that the Math object is an ugly artifact ?
> > Well, here's a nice way of getting rid of it :

>
> Artifact of not - that's questionable, because some methods fit to
> numbers (e.g. .round(), other), some by semantic - for mathematical
> actions and could be placed in separate Math'ematical module.

Why the hell given that numbers are objects too, can't they have their
own methods in their own prototype ?
Why if not to copy Java style were they moved into a separate "Math"
object ?
In order to make it an "optional" object (as Crockford states in that
video #2) for lesser ES implementations ?
--
Jorge.

Jorge, Feb 17, 2010
12. ### Thomas 'PointedEars' LahnGuest

kangax wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Cody Haines wrote:
>>> Jorge wrote:
>>>> Do you think -as I do- that the Math object is an ugly artifact ?
>>>> Well, here's a nice way of getting rid of it :
>>>>
>>>> Number.prototype.sin= function () { return Math.sin(+this); };
>>>> [...]
>>>> (1.234).sin().asin()
>>>> [...]
>>>
>>> Just out of curiosity, does IE support this? I don't see why it
>>> wouldn't, just making sure

>>
>> [...]
>> In fact, given that, according to Editions 3 and 5 of the ECMAScript
>> Language Specification, when evaluating the CallExpression's
>> /MemberExpression/ any primitive value would be converted into an
>> appropriate value of type Object (ES3/5, 11.2.3, 11.2.1, and 9.9), this
>> SHOULD work everywhere where `Number.prototype' is supported (which
>> AFAIK excludes only JavaScript 1.0 as of Netscape 2.x, and JScript 1.0
>> as of IE 3.0 and IIS 3.0 ).Â¹ [...]
>> ___________
>> Â¹ To be sure of that, I have debugged the algorithms of ECMAScript Ed.
>> 5,
>> and compared with Ed. 3; I can post more detailed results of my
>> research if anyone is interested.

>
> I'm interested.

In the following, I will use `Number.prototype.sin' as defined above and
`(1.234).sin()' for the example.

The basic productions that apply to the expression

(1.234).sin()

in both Editions are:

CallExpression :
MemberExpression Arguments

MemberExpression :
PrimaryExpression
MemberExpression . Identifier

PrimaryExpression :
Literal
( Expression )

Expression :
AssignmentExpression

...

LeftHandSideExpression :
NewExpression

NewExpression:
MemberExpression

Literal ::
NumericLiteral

NumericLiteral ::
DecimalLiteral

DecimalLiteral ::
DecimalIntegerLiteral . DecimalDigits_opt ExponentPart_opt

Arguments :
()

As a result, the following unifications take place:

In the algorithm for the production
CallExpression : MemberExpression Arguments
(section 11.2.3):

CallExpression := (1.234).sin()
MemberExpression := (1.234).sin
Arguments := ()

And the following steps:

1. Evaluate MemberExpression.

In the algorithm for
MemberExpression : MemberExpression [ Expression ]
(section 11.2.1):

MemberExpression := (1.234)
Expression := "sin"

Steps per ES3F:

1. Evaluate MemberExpression.
--> Result(1) := 1.234
2. Call GetValue(Result(1)).
--> Result(2) := 1.234
3. Evaluate Expression.
--> Result(3) := "sin"
4. Call GetValue(Result(1)).
--> Result(4) := "sin"
5. Call ToObject(Result(2)).
^^^^^^^^^^^^^^^^^^^^^^^^^

(9.9) ToObject

The operator ToObject converts its argument to a value
of type Object according to the following table:

[...]
Number Create a new Number object whose [[value]] property is
set to the value of the number. See section 15.7 for a
description of Number objects.
[...]

--> Result(5) := new Number(1.234)

6. Call ToString(Result(4)).
--> Result(6) := "sin"
7. Return Reference(base=Result(5), name=Result(6)):
--> Return Reference(base=new Number(1.234), name="sin").

It is thus quite obvious already that the primitive Number value is being
converted into an equivalent Number object that has the current value of
`Number.prototype' next in its prototype chain, and we can skip analyzing
the subsequent steps for ES3F in detail. JFTR, they are:

2. Evaluate /Arguments/, producing an internal list of argument values
(section 11.2.4).
3. Call GetValue(Result(1)).
4. If Type(Result(3)) is not Object, throw a *TypeError* exception.
5. If Result(3) does not implement the internal [[Call]] method, throw
a TypeError exception.
6. If Type(Result(1)) is Reference, Result(6) is GetBase(Result(1)).
Otherwise, Result(6) is *null*.
7. If Result(6) is an activation object, Result(7) is *null*.
Otherwise, Result(7) is the same as Result(6).
8. Call the [[Call]] method on Result(3), providing Result(7) as the
*this* value and providing the list Result(2) as the argument values.
9. Return Result(8).

However, the conversion of the primitive value to an object for the purpose
of property lookup is a lot harder to see with the ES5 algorithms, which is
why I am going deeply into detail there:

(11.2.3) Function Calls

The production /CallExpression/ : /MemberExpression/ /Arguments/
is evaluated as follows:

1. Let /ref/ be the result of evaluating /MemberExpression/.

--> ref := Evaluate( (1.234).sin )

(11.2.1) Property Accessors

[...]
The production
/MemberExpression/ : /MemberExpression/ [ /Expression/ ]"
(equivalence of dot and bracket property accessor notation for
Identifiers; the ed.) is evaluated as follows:

MemberExpression := (1.234)
Expression := "sin"

1. Let /baseReference/ be the result of evaluating
/MemberExpression/.
--> baseReference := 1.234

2. Let /baseValue/ be GetValue(/baseReference/).
--> baseValue := GetValue(baseReference)
--> baseValue := 1.234

3. Let /propertyNameReference/ be the result of evaluating
/Expression/.
--> propertyNameReference := "sin"

4. Let /propertyNameValue/ be GetValue(/propertyNameReference/).
--> propertyNameValue := "sin"

5. Call CheckObjectCoercible(/baseValue/).
--> CheckObjectCoercible(1.234) exits normally

6. Let /propertyNameString/ be ToString(/propertyNameValue/).
--> propertyNameString := "sin"

7. If the syntactic production that is being evaluated is contained
in strict mode code, let /strict/ be *true*, else let /strict/ be
*false*.

We assume no strict mode here (it does not really matter for this
algorithm anyway) --> strict := false

8. Return a value of type Reference whose base value is /baseValue/
and whose referenced name is /propertyNameString/, and whose
strict mode flag is /strict/.
--> return Reference(base=1.234, name="sin", strict=false)

--> ref := Reference(base=1.234, name="sin", strict=false)

(11.2.3)
2. Let /func/ be GetValue(/ref/).
--> func := GetValue(ref)

(8.7.1) GetValue(V)

V := Reference(base=1.234, name="sin", strict=false)

1. If Type(/V/) is not Reference, return /V/.
--> Type(V) is Reference, continue.

2. Let /base/ be the result of calling GetBase(/V/).
--> base := GetBase(V)
--> base := 1.234 (section 8.7)

3. If IsUnresolvableReference(/V/), throw a *ReferenceError*
exception.

V := Reference(base=1.234, name="sin", strict=false)

(8.7)
IsUnresolvableReference(V) := (GetBase(V) == undefined)
--> IsUnresolvableReference(V) == false

--> Continue.

4. If IsPropertyReference(/V/), then

V := Reference(base=1.234, name="sin", strict=false)

(8.7)
IsPropertyReference(V) :=
Type(V) == Object || HasPrimitiveBase(V)

--> Type(V) == Number

HasPrimitiveBase(V) := Type(GetBase(V)) == Boolean
|| Type(GetBase(V)) == String
|| Type(GetBase(V)) == Number
--> HasPrimitiveBase(V) == true

--> IsPropertyReference(V) == true

a. If HasPrimitiveBase(V) is false, then let /get/ be the
[[Get]] internal method of /base/, otherwise let /get/
be the special [[Get]] internal method defined below.
--> HasPrimitiveBase(V) == true
--> get := special [[Get]]

b. Return the result of calling the /get/ internal method
using /base/ as its *this* value, and passing
GetReferencedName(/V/) for the argument.

--> return get(this=1.234, "sin")
--> return special [[Get]](this=1.234, "sin")

1. Let O be ToObject(base).
^^^^^^^^^^^^^^^^^^^^^^^^
--> O := ToObject(1.234)
--> O := new Number(1.234)

2. Let /desc/ be the result of calling the
[[GetProperty]] internal method of /O/
with property name /P/.

desc := (new Number(1.234)).[[GetProperty]]("sin")

(8.12.2) [[GetProperty]] (P)

When the [[GetProperty]] internal method of /O/
is called with property name /P/, the following
steps are taken:

O := new Number(1.234)
P := "sin"

1. Let /prop/ be the result of calling the
[[GetOwnProperty]] internal method of /O/
with property name /P/.

prop :=
(new Number(1.234))[[GetOwnProperty]]("sin")

(8.12.1) [[GetOwnProperty]] (P)

When the [[GetOwnProperty]] internal method of
/O/ is called with property name /P/, the
following steps are taken:

1. If /O/ doesnâ€™t have an own property with
name /P/, return *undefined*.

HasOwnProperty(new Number(1.234), "sin")
== false
--> return undefined

--> prop := undefined

2. If /prop/ is not *undefined*, return /prop/.
--> prop == undefined
--> Continue.

3. Let /proto/ be the value of the [[Prototype]]
internal property of /O/.
--> proto := (new Number(1.234))[[Prototype]]
--> proto := Number.prototype

4. If /proto/ is *null*, return *undefined*.
--> proto != null
--> Continue.

5. Return the result of calling the
[[GetProperty]] internal method of /proto/
with argument /P/.
--> return (
Number.prototype.[[GetProperty]]("sin"))

1. prop :=
Number.prototype[[GetOwnProperty]]("sin")

1. HasOwnProperty(Number.prototype, "sin")
== true, continue.
2. D := PropertyDescriptor()
3. X := Property(Number.prototype, "sin")
4. X is a data property (section 8.6), so
a. D.[[Value]] := X.[[Value]]
b. D.[[Writeable]] := X.[[Writeable]]
5. Else ... (skipped accordingly)
6. D.[[Enumerable]] := X.[[Enumerable]]
7. D.[[Configurable]] := X.[[Configurable]]
8. Return D.

--> return PropertyDescriptor(
Number.prototype, "sin", attribs)

--> desc := PropertyDescriptor(
Number.prototype, "sin", attribs)

3. If /desc/ is undefined, return *undefined*.
--> PropertyDescriptor(...) != undefined, continue.

4. If IsDataDescriptor(/desc/) is *true*, return
desc.[[Value]].

== true:

(8.10.2)
1. PropertyDescriptor(Number.prototype, "sin",
attribs) != undefined, continue.
2. PropertyDescriptor(Number.prototype, "sin",
attribs).[[Value]] present, continue.
3. Return true.

--> Return PropertyDescriptor(...).[[Value]],
--> Return Number.prototype.sin.

--> return Number.prototype.sin

--> func := Number.prototype.sin

(11.2.3)
3. Let /argList/ be the result of evaluating /Arguments/, producing an
internal list of argument values (see 11.2.4).
--> argList := List()

4. If Type(/func/) is not Object, throw a *TypeError* exception.
--> Type(Number.prototype.sin) == Object, continue.

5. If IsCallable(/func/) is *false*, throw a *TypeError* exception.
--> IsCallable(Number.prototype.sin) == true, continue.

6. If Type(/ref/) is Reference, then
--> Type(Reference(base=1.234, name="sin", strict=false))
== Reference, so

a. If IsPropertyReference(/ref/) is true, then
--> IsPropertyReference(
Reference(base=1.234, name="sin", strict=false))
== true, so

i. Let thisValue be GetBase(/ref/).
--> thisValue := GetBase(ref)
--> thisValue := 1.234

b. Else ... (skipped accordingly)

7. Else ... (skipped accordingly)

8. Return the result of calling the [[Call]] internal method on /func/,
providing /thisValue/ as the *this* value and providing the list
/argList/ as the argument values.

--> return (Number.prototype.sin.[[Call]](
this=1.234, arguments=List())

(13.2.1) [[Call]]

When the [[Call]] internal method for a Function object /F/ is
called with a *this* value and a list of arguments, the
following steps are taken:

1. Let /funcCtx/ be the result of establishing a new execution
context for function code using the value of /F/'s
[[FormalParameters]] internal property, the passed arguments
List /args/, and the *this* value as described in 10.4.3.

--> funcCtx := ExecutionContext(
formalParameters=
Number.prototype.sin.[[FormalParameters]],
arguments=List(),
this=1.234)

2. Let result be the result of evaluating the /FunctionBody/
that is the value of /F/'s [
Code (Text):
] internal property. If
/F/ does not have a [[Code]] internal property or if its
value is an empty FunctionBody, then result is (normal,
undefined, empty).

--> result := Evaluate(Number.prototype.sin.[[Code]])

3. Exit the execution context /funcCtx/, restoring the previous
execution context.
--> Exit(funcCtx), ...

4. If /result/.type is |throw| then throw /result/.value.
--> result.type == normal, continue.

5. If /result/.type is |return| then return /result/.value.
--> result.type == return
--> return /result/.value

--> return the equivalent of
Number.prototype.sin.apply(1.234, argList)

--> return Math.sin(+1.234)
--> return Math.sin(1.234)

What I found most interesting here is that the primitive value is converted
to an object solely for the purpose of property lookup; and that the
primitive value, _not_ a reference to that object becomes the `this' value
of the called method.  (IOW, if the `this' value of such a method is used
repeatedly with property accessors, it could be more efficient to convert
it to an object once explicitly, and then use the object reference

I have also learned in the process that the more complex algorithms of ES5
do have a purpose beyond simply much a greater abstraction level; for
example, they support the implementation of mutable property attributes
like [[Enumerable]] -- which finally would allow such nice features like

var o = {foo: "bar"};

/* shows "foo" */
for (var p in o) console.log(p);

Object.defineProperty(o, "bar", {enumerable: false});

/* shows nothing */
for (p in o) console.log(p);

(if they were implemented; not so in JavaScript 1.8.1 as of
Firefox/Iceweasel 3.5.6 or any other widely distributed implementationÂ¹) --
and facilitate making the difference between data properties and accessor
properties, i.e. normal properties on the one hand, and properties with
getters/setters on the other hand (already implemented there and
elsewhereÂ¹):

var o = {
_bar: "",
get foo() { return +this._bar; },
set foo(x) { this._bar = String(+x + 19); }
};

o.foo = "23";

/* shows 42 as a number */
console.log(o.foo);

PointedEars
___________
Â¹  <http://www.robertnyman.com/javascript/javascript-getters-setters.html>
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

Thomas 'PointedEars' Lahn, Feb 17, 2010
13. ### Thomas 'PointedEars' LahnGuest

Richard Cornford wrote:

> In ES3 the - this - keyword always refers to an object, so you are
> guaranteed that it is never a primitive value. [...]

ISTM that I have just proved this to be a common misconception.

PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Thomas 'PointedEars' Lahn, Feb 17, 2010
14. ### JorgeGuest

On Feb 17, 11:54 am, Thomas 'PointedEars' Lahn <>
wrote:
> Richard Cornford wrote:
> > In ES3 the - this - keyword always refers to an object, so you are
> > guaranteed that it is never a primitive value. [...]

>
> ISTM that I have just proved this to be a common misconception.

He said *In*ES3*:

Number.prototype.test= function () { return typeof this; };
(1).test()
--> "object"
--
Jorge.

Jorge, Feb 17, 2010
15. ### Thomas 'PointedEars' LahnGuest

Thomas 'PointedEars' Lahn wrote:

> Richard Cornford wrote:
>> In ES3 the - this - keyword always refers to an object, so you are
>> guaranteed that it is never a primitive value. [...]

>
> ISTM that I have just proved this to be a common misconception.

Please ignore this. In fact, my researchÂ¹ proves that you are correct for
ES3(F), where the Reference value is computed using the conversion result as
base; not so in ES5 (I wonder what the rationale was).

PointedEars
___________
Â¹ <news:>
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)

Thomas 'PointedEars' Lahn, Feb 17, 2010
16. ### Thomas 'PointedEars' LahnGuest

Stefan Weiss wrote:

> On 17/02/10 11:52, Thomas 'PointedEars' Lahn wrote:
>
> [snip impressive human-script-engine-mode text]

Thanks Some day soon I hope I can have *computed* what should happen
according to the Specification for any given input or at least any given

>> I have also learned in the process that the more complex algorithms of
>> ES5 do have a purpose beyond simply much a greater abstraction level;
>> for example, they support the implementation of mutable property
>> attributes like [[Enumerable]] -- which finally would allow such nice
>> features like
>>
>> var o = {foo: "bar"};
>>
>> /* shows "foo" */
>> for (var p in o) console.log(p);
>>
>> Object.defineProperty(o, "bar", {enumerable: false});

^^^^^
>> /* shows nothing */
>> for (p in o) console.log(p);

>
> Shouldn't this still show "foo"?

It should, thanks. I meant to pass "foo", of course.

PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)

Thomas 'PointedEars' Lahn, Feb 17, 2010
17. ### Richard CornfordGuest

On Feb 17, 9:39 am, Jorge <> wrote:
> On Feb 17, 10:33 am, "Richard Cornford" <>
> wrote:
>
>
>
> > - implies two numeric primitive to Number object type-conversations

>
> One sometimes has to wonder what's really going on inside one's
> browser... "primitive" "conversations" ? LOL.

OK, "conversations" should have been "conversions" (automatic spelling
correction, which I usually have turned off because it is not very
good at guessing which words are likely to occur in the subjects I

Richard.

Richard Cornford, Feb 17, 2010
18. ### Richard CornfordGuest

On Feb 17, 11:12 am, Thomas 'PointedEars' Lahn wrote:
<snip>
> ... , my research¹ proves that you are correct for ES3(F),
> where the Reference value is computed using the conversion
> result as base; not so in ES5 (I wonder what the rationale
> was).

You mean the rationale for designing a new language version
specification that is significantly incompatible with the (very long
established) preceding version (and so is going to give many people
headaches in the near future as ES 5 implementations replace ES 3
implementations in web browsers)?

As I recall from the discussions on the ES mailing lists there wasn't
much of a rationale, just vague talk of things like "security" and a
few outspoken supporters of the notion.

You may recall that Google Chrome had been observed to be getting this
aspect of ES3 wrong (with regard to String object methods in those
cases) long before there was an ES5 (or this change had been
proposed), so for at least one of the participants in the ECMA
committee getting the change passed meant not having to fix what had
previously been a faulty script engine.

Richard.

Richard Cornford, Feb 17, 2010
19. ### JorgeGuest

Jorge, Feb 17, 2010
20. ### Thomas 'PointedEars' LahnGuest

Jake Jarvis wrote:

> On 17.02.2010 09:36, wrote Jorge:
>> Thomas 'PointedEars' Lahn wrote:
>>> (...) In fact, this idea is anything but original. (...)

>>
>> And then came Pointy, decided to spoil the fun...
>>
>> I've never seen it before.. who, where, when ? Have you got any urls,
>> plz ? [...]

>
> http://www.prototypejs.org

The idea of augmenting built-in prototypes, particularly Number.prototype,
is much, much older than that. It dates back to at least 2001 CE. Google

PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q\$253\$1\$> (2004)

Thomas 'PointedEars' Lahn, Feb 17, 2010