Math ugliness.

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

  1. Jorge

    Jorge Guest

    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
    #1
    1. Advertising

  2. Jorge

    Cody Haines Guest

    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
    #2
    1. Advertising

  3. Jorge

    RobG Guest

    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
    #3
  4. 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
    #4
  5. 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 was curious about this too.
    >
    > 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
    #5
  6. Jorge

    Jorge Guest

    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
    much/any further ado/testing.
    --
    Jorge.
    Jorge, Feb 17, 2010
    #6
  7. Jorge

    Jorge Guest

    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
    #7
  8. 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
    #8
  9. Jorge

    Jorge Guest

    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
    #9
  10. Jorge

    Jorge Guest

    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
    #10
  11. Jorge

    Jorge Guest

    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
    #11
  12. 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]].

    --> IsDataDescriptor(PropertyDescriptor(...))
    == 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:
    ] 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
    instead.)
    
    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
    #12
  13. 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
    #13
  14. Jorge

    Jorge Guest

    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
    #14
  15. 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
    #15
  16. 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
    expression instead.

    >> 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
    #16
  17. 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
    write about).

    Richard.
    Richard Cornford, Feb 17, 2010
    #17
  18. 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
    #18
  19. Jorge

    Jorge Guest

    Jorge, Feb 17, 2010
    #19
  20. 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
    is your friend. [psf 6.1]


    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
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. chirs
    Replies:
    18
    Views:
    763
    Chris Uppal
    Mar 2, 2004
  2. AciD_X
    Replies:
    4
    Views:
    8,098
    Jonathan Turkanis
    Apr 1, 2004
  3. Mark Healey
    Replies:
    7
    Views:
    1,479
    Tim Prince
    May 22, 2006
  4. C Erler
    Replies:
    3
    Views:
    132
    Ara.T.Howard
    Jun 28, 2005
  5. VK
    Replies:
    15
    Views:
    1,161
    Dr J R Stockton
    May 2, 2010
Loading...

Share This Page