Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #16740 > unrolled thread

Built-in native method

Started byCezary Tomczyk <cezary.tomczyk@gmail.com>
First post2012-10-19 22:07 +0200
Last post2012-10-28 19:53 +0100
Articles 20 on this page of 27 — 6 participants

Back to article view | Back to comp.lang.javascript


Contents

  Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-19 22:07 +0200
    Re: Built-in native method JJ <jaejunks_at@_googlemail_dot._com> - 2012-10-21 06:44 +0000
      Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-21 18:46 +0200
      Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-21 19:37 +0200
        Re: Built-in native method Andreas Bergmaier <andber93@web.de> - 2012-10-22 15:47 +0200
          Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-22 18:00 +0200
            Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-24 02:17 +0100
              Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-24 22:17 +0200
                Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-25 00:32 +0200
    Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-24 02:15 +0100
      Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-24 22:35 +0200
        Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-25 00:03 +0200
          Re: Built-in native method Asen Bozhilov <asen.bozhilov@gmail.com> - 2012-10-26 03:58 -0700
            Re: Built-in native method RobG <rgqld@iinet.net.au> - 2012-10-29 16:39 -0700
          Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 15:32 +0100
            Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-28 17:05 +0100
              Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 18:39 +0100
                Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-28 20:10 +0100
                  Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 20:23 +0100
                    Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-28 21:23 +0100
                      Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 22:03 +0100
          Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 15:49 +0100
            Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-28 17:12 +0100
              Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 17:49 +0100
                Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-28 18:07 +0100
                  Re: Built-in native method Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-10-28 19:22 +0100
                    Re: Built-in native method Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-28 19:53 +0100

Page 1 of 2  [1] 2  Next page →


#16740 — Built-in native method

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-19 22:07 +0200
SubjectBuilt-in native method
Message-ID<k5sbuj$bt8$1@speranza.aioe.org>
I have read this article: 
http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/

At the end there is:

"[...] It should be now clear that extending native built-ins is 
definitely not as risky as messing with host objects. Do it carefully, 
follow spec closely, and use your reasonable judgement.[...]"

In my project I use some of the 3-rd party library. I didn't knew that 
this library overwritten many of built-in native methods. And even 
worst, they work different than they should. I mean, results is not the 
same as expected.

So, when I'm doing:

if (String.prototype.trim)

and its passed then this means that trim method exists. The only problem 
is that I cannot be sure if this works correctly or if the native 
built-in method is not overwritten by someone else.

Is there a way to check if (for example: String.prototype.trim) is a 
real built-in method?

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [next] | [standalone]


#16762

FromJJ <jaejunks_at@_googlemail_dot._com>
Date2012-10-21 06:44 +0000
Message-ID<XnsA0F38C4E46019jaejunksgooglemailco@0.0.0.44>
In reply to#16740
Cezary Tomczyk <cezary.tomczyk@gmail.com> wrote:
> So, when I'm doing:
> 
> if (String.prototype.trim)
> 
> and its passed then this means that trim method exists. The only problem 
> is that I cannot be sure if this works correctly or if the native 
> built-in method is not overwritten by someone else.
> 
> Is there a way to check if (for example: String.prototype.trim) is a 
> real built-in method?

The code inside native functions are syntatically incorrect. You can use 
this to check them. For example, the "escape" function (any function will 
do):

var a=escape.toString();
console.log(a);
//Firefox/Safari: "function escape() {\n    [native code]\n}"
//Chrome/MSIE/Opera: "function escape() { [native code] }"

You see that the code contains only an expression, which is an array. The 
array contains only one expression, which is "native code". i.e.: two 
references to identifiers which are neither reserved word, variable, 
function nor object. This expression is not correct and will cause a syntax 
error exception.

The easiest way to check it is to use the "eval" function to check whether 
an existing function is syntatically correct or not.

function isNativeFunc(f) {
  var a, z;
  if (typeof f == 'function') {
    //is a function
    try {
      a = f.toString();
      eval('(function(){'+a+'})()');
      return false;
    } catch(z) {
      //syntax error
      return true;
    }
  } else {
    //not a function. assume false
    return false;
  }
}

console.log(isNativeFunc(escape));
//shows: true
console.log(isNativeFunc(isNativeFunc));
//shows: false

Note that the usage of "eval" is considered as unsafe. So, since there's no 
direct alternative for that method, parsing is neccessary. A regular 
expression is used for this method.

function isNativeFunc(f) {
  if (typeof f == 'function') {
    //is a function
    var a = f.toString();
    //reg-exp for native function code block format
    var r = /[^{]+\{[\n ]+\[[a-z]+ [a-z]+\][\n ]+\}$/im;
    return a.match(r) != null;
  } else {
    //not a function. assume false
    return false;
  }
}

console.log(isNativeFunc(escape));
//shows: true
console.log(isNativeFunc(isNativeFunc));
//shows: false

[toc] | [prev] | [next] | [standalone]


#16765

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-21 18:46 +0200
Message-ID<k618t0$2d5$1@speranza.aioe.org>
In reply to#16762
W dniu 2012-10-21 08:44, JJ pisze:
> Cezary Tomczyk <cezary.tomczyk@gmail.com> wrote:
>> So, when I'm doing:
>>
>> if (String.prototype.trim)
>>
>> and its passed then this means that trim method exists. The only problem
>> is that I cannot be sure if this works correctly or if the native
>> built-in method is not overwritten by someone else.
>>
>> Is there a way to check if (for example: String.prototype.trim) is a
>> real built-in method?
>
> The code inside native functions are syntatically incorrect. You can use
> this to check them. For example, the "escape" function (any function will
> do):
>
> var a=escape.toString();
> console.log(a);
> //Firefox/Safari: "function escape() {\n    [native code]\n}"
> //Chrome/MSIE/Opera: "function escape() { [native code] }"
>
> You see that the code contains only an expression, which is an array. The
> array contains only one expression, which is "native code". i.e.: two
> references to identifiers which are neither reserved word, variable,
> function nor object. This expression is not correct and will cause a syntax
> error exception.

I completely forgot about "[native code]".

> The easiest way to check it is to use the "eval" function to check whether
> an existing function is syntatically correct or not.
>
> function isNativeFunc(f) {
>    var a, z;
>    if (typeof f == 'function') {
>      //is a function
>      try {
>        a = f.toString();
>        eval('(function(){'+a+'})()');
>        return false;
>      } catch(z) {
>        //syntax error
>        return true;
>      }
>    } else {
>      //not a function. assume false
>      return false;
>    }
> }
>
> console.log(isNativeFunc(escape));
> //shows: true
> console.log(isNativeFunc(isNativeFunc));
> //shows: false
>
> Note that the usage of "eval" is considered as unsafe. So, since there's no
> direct alternative for that method, parsing is neccessary. A regular
> expression is used for this method.
>
> function isNativeFunc(f) {
>    if (typeof f == 'function') {
>      //is a function
>      var a = f.toString();
>      //reg-exp for native function code block format
>      var r = /[^{]+\{[\n ]+\[[a-z]+ [a-z]+\][\n ]+\}$/im;
>      return a.match(r) != null;
>    } else {
>      //not a function. assume false
>      return false;
>    }
> }
>
> console.log(isNativeFunc(escape));
> //shows: true
> console.log(isNativeFunc(isNativeFunc));
> //shows: false

Thank you for explanation. Make sense. I have no more questions in this 
topic.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16766

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-21 19:37 +0200
Message-ID<k61bt0$b4a$1@speranza.aioe.org>
In reply to#16762
W dniu 2012-10-21 08:44, JJ pisze:
> Cezary Tomczyk <cezary.tomczyk@gmail.com> wrote:
[...]
> function isNativeFunc(f) {
>    if (typeof f == 'function') {
>      //is a function
>      var a = f.toString();
>      //reg-exp for native function code block format
>      var r = /[^{]+\{[\n ]+\[[a-z]+ [a-z]+\][\n ]+\}$/im;
>      return a.match(r) != null;
>    } else {
>      //not a function. assume false
>      return false;
>    }
> }

I've just little bit improved the code:
http://jsfiddle.net/DbGVS/

Any advice or comments are appreciated.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16792

FromAndreas Bergmaier <andber93@web.de>
Date2012-10-22 15:47 +0200
Message-ID<k63ip3$lj4$1@news.albasani.net>
In reply to#16766
Cezary Tomczyk schrieb:
> I've just little bit improved the code:
> http://jsfiddle.net/DbGVS/
>
> Any advice or comments are appreciated.

It must be a bit more complicated. Also non-native functions can contain 
the string '[native code]' - most prominently your isNativeMethod 
function: http://jsfiddle.net/DbGVS/3/

regards,
  Bergi

[toc] | [prev] | [next] | [standalone]


#16799

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-22 18:00 +0200
Message-ID<k63qjg$2b4$1@speranza.aioe.org>
In reply to#16792
W dniu 2012-10-22 15:47, Andreas Bergmaier pisze:
> Cezary Tomczyk schrieb:
>> I've just little bit improved the code:
>> http://jsfiddle.net/DbGVS/
>>
>> Any advice or comments are appreciated.
>
> It must be a bit more complicated. Also non-native functions can contain
> the string '[native code]' - most prominently your isNativeMethod
> function: http://jsfiddle.net/DbGVS/3/

Yes, it's is possible. There is a risk. At this moment I don't know 
better method.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16828

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-24 02:17 +0100
Message-ID<2863979.M2cLrOPMcC@PointedEars.de>
In reply to#16799
Cezary Tomczyk wrote:

> W dniu 2012-10-22 15:47, Andreas Bergmaier pisze:
>> Cezary Tomczyk schrieb:
>>> I've just little bit improved the code:
>>> http://jsfiddle.net/DbGVS/
>>>
>>> Any advice or comments are appreciated.
>>
>> It must be a bit more complicated. Also non-native functions can contain
>> the string '[native code]' - most prominently your isNativeMethod
>> function: http://jsfiddle.net/DbGVS/3/
> 
> Yes, it's is possible. There is a risk. At this moment I don't know
> better method.

The better way is to cure the disease and not the symptoms: Use a better 
library in the first place, and tell the author(s) of the first library
that and how they screwed up so that they can learn from that mistake and 
make it better.


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

[toc] | [prev] | [next] | [standalone]


#16839

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-24 22:17 +0200
Message-ID<k69ic1$o34$1@speranza.aioe.org>
In reply to#16828
W dniu 2012-10-24 03:17, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:
>
>> W dniu 2012-10-22 15:47, Andreas Bergmaier pisze:
>>> Cezary Tomczyk schrieb:
>>>> I've just little bit improved the code:
>>>> http://jsfiddle.net/DbGVS/
>>>>
>>>> Any advice or comments are appreciated.
>>>
>>> It must be a bit more complicated. Also non-native functions can contain
>>> the string '[native code]' - most prominently your isNativeMethod
>>> function: http://jsfiddle.net/DbGVS/3/
>>
>> Yes, it's is possible. There is a risk. At this moment I don't know
>> better method.
>
> The better way is to cure the disease and not the symptoms: Use a better
> library in the first place, and tell the author(s) of the first library
> that and how they screwed up so that they can learn from that mistake and
> make it better.

Oh well. I would like to tell them, but they probably will not be listen.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16844

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-25 00:32 +0200
Message-ID<3522868.MSM1jvRdVV@PointedEars.de>
In reply to#16839
Cezary Tomczyk wrote:

> W dniu 2012-10-24 03:17, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
>>> W dniu 2012-10-22 15:47, Andreas Bergmaier pisze:
>>>> Cezary Tomczyk schrieb:
>>>>> I've just little bit improved the code:
>>>>> http://jsfiddle.net/DbGVS/
>>>>>
>>>>> Any advice or comments are appreciated.
>>>> It must be a bit more complicated. Also non-native functions can
>>>> contain the string '[native code]' - most prominently your
>>>> isNativeMethod function: http://jsfiddle.net/DbGVS/3/
>>> Yes, it's is possible. There is a risk. At this moment I don't know
>>> better method.
>> The better way is to cure the disease and not the symptoms: Use a better
>> library in the first place, and tell the author(s) of the first library
>> that and how they screwed up so that they can learn from that mistake and
>> make it better.
> 
> Oh well. I would like to tell them, but they probably will not be listen.

The logical course of action should be clear by now.


PointedEars
-- 
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

[toc] | [prev] | [next] | [standalone]


#16829

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-24 02:15 +0100
Message-ID<67583587.7BbXikoxoM@PointedEars.de>
In reply to#16740
Cezary Tomczyk wrote:

> I have read this article:
> http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/
> 
> At the end there is:
> 
> "[...] It should be now clear that extending native built-ins is
> definitely not as risky as messing with host objects. Do it carefully,
> follow spec closely, and use your reasonable judgement.[...]"
> 
> In my project I use some of the 3-rd party library. I didn't knew that
> this library overwritten many of built-in native methods.

Do not use that library then; it is junk.  A library should only overwrite 
built-in methods (that is, the properties that refer to the respective 
Function objects) when they do _not_ exist, or are not as capable as 
required (if it is reasonable to use this and no other method).  Built-in 
methods are inevitably faster than user-defined ones because in most of the 
cases the former are already compiled.

Any library that provides an emulation of a built-in method should only do 
that after it has been determined that the built-in method is unavailable:

  if (typeof foo.whatever != "function")
  {
    foo.whatever = function (…) {
      …
    };
  }

or even

  if (typeof foo.whatever != "undefined")
  {
    foo.whatever = function (…) {
      …
    };
  }

`foo' should not refer to a host object then.  And whenever a built-in 
method is overwritten by a library, it should be done so that the specified 
way of calling that method is still supported.

For example, it has been reasonable (but may be considered obsolete now) to 
overwrite a not-as-capable Math.max() method:

  /**
   * Returns the numeric maximum of all arguments.
   * 
   * @params : Number
   * @return {Number}
   *   <code>-Infinity</code> if no arguments have been passed.
   */
  function Math_max ()
  {
    var result = Number.NEGATIVE_INFINITY;

    /* NOTE: Array.prototype.slice() was not specified before ES 3 */
    for (var i = arguments.length; i--;)
    {
      var arg = parseFloat(arguments[i]);
      if (arg > result)
      {
        result = arg;
      }
    }

    return result;
  }

  var x;

  if (typeof Math.max == "function")
  {
    x = Math.max(1, 2, 3);
  }

  if (typeof x == "undefined" || x != 3)
  {
    Math.max = Math_max;
  }

> And even worst, they work different than they should. I mean, results is
> not the same as expected.
> 
> So, when I'm doing:
> 
> if (String.prototype.trim)
> 
> and its passed then this means that trim method exists.

No, it means that the String prototype object has a `trim' property whose 
value can be type-converted to `true'.

> Is there a way to check if (for example: String.prototype.trim) is a
> real built-in method?

No (looking for "[native code]" is _not_ reliable; function serialization is 
*implementation-dependent*), and there should not be a need for it.  
However, you can increase the probabililty that the property (value) is 
callable, and you can handle odd cases (this may be part of a user-defined 
wrapper):

  if (typeof bar.trim == "function")
  {
    try
    {
      var foo = bar.trim();
    }
    catch (e)
    {
      …
    }
  }

try-catch might need to be guarded for a maximum of backwards-compatibility:

  if (typeof bar.trim == "function")
  {
    eval("try { var foo = bar.trim(); }"
       + "catch (e) { … }");
  }

See also: http://PointedEars.de/es-matrix>


PointedEars
-- 
> If you get a bunch of authors […] that state the same "best practices"
> in any programming language, then you can bet who is wrong or right...
Not with javascript. Nonsense propagates like wildfire in this field.
  -- Richard Cornford, comp.lang.javascript, 2011-11-14

[toc] | [prev] | [next] | [standalone]


#16840

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-24 22:35 +0200
Message-ID<k69jek$r9i$1@speranza.aioe.org>
In reply to#16829
W dniu 2012-10-24 03:15, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:
>
>> I have read this article:
>> http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/
>>
>> At the end there is:
>>
>> "[...] It should be now clear that extending native built-ins is
>> definitely not as risky as messing with host objects. Do it carefully,
>> follow spec closely, and use your reasonable judgement.[...]"
>>
>> In my project I use some of the 3-rd party library. I didn't knew that
>> this library overwritten many of built-in native methods.
>
> Do not use that library then; it is junk.  A library should only overwrite

Sometimes it is just impossible. And especially you should know about that.

> built-in methods (that is, the properties that refer to the respective
> Function objects) when they do _not_ exist, or are not as capable as
> required (if it is reasonable to use this and no other method).  Built-in
> methods are inevitably faster than user-defined ones because in most of the
> cases the former are already compiled.

Generally speaking I agree. However, I don't why they wrote many methods 
in a wrong way. I can't relay on their methods and that's why I just 
wanted to check if method is really native method. There is no perfect 
solution.

> Any library that provides an emulation of a built-in method should only do
> that after it has been determined that the built-in method is unavailable:

Yes, but only on one condition: if developer know how to do it in right way.

>    if (typeof foo.whatever != "function")

I would use !== here. Its slightly faster than != because there is no 
type conversion.

>    {
>      foo.whatever = function (…) {
>        …
>      };
>    }
>
> or even
>
>    if (typeof foo.whatever != "undefined")
>    {
>      foo.whatever = function (…) {
>        …
>      };
>    }
>
> `foo' should not refer to a host object then.  And whenever a built-in
> method is overwritten by a library, it should be done so that the specified
> way of calling that method is still supported.

But if foo.whatever is defined then I'm not sure if this foo.whatever 
working as expected. I mean, as defined in documentation. For example: 
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/Trim

Maybe its good to write here small unit test and try to check what is 
the result from method foo.whatever. Then I can be sure if the method 
working well or not.

Am I correct?

> For example, it has been reasonable (but may be considered obsolete now) to
> overwrite a not-as-capable Math.max() method:
>
>    /**
>     * Returns the numeric maximum of all arguments.
>     *
>     * @params : Number
>     * @return {Number}
>     *   <code>-Infinity</code> if no arguments have been passed.
>     */
>    function Math_max ()
>    {
>      var result = Number.NEGATIVE_INFINITY;
>
>      /* NOTE: Array.prototype.slice() was not specified before ES 3 */
>      for (var i = arguments.length; i--;)
>      {
>        var arg = parseFloat(arguments[i]);
>        if (arg > result)
>        {
>          result = arg;
>        }
>      }
>
>      return result;
>    }
>
>    var x;
>
>    if (typeof Math.max == "function")
>    {
>      x = Math.max(1, 2, 3);
>    }
>
>    if (typeof x == "undefined" || x != 3)
>    {
>      Math.max = Math_max;
>    }
>
>> And even worst, they work different than they should. I mean, results is
>> not the same as expected.
>>
>> So, when I'm doing:
>>
>> if (String.prototype.trim)
>>
>> and its passed then this means that trim method exists.
>
> No, it means that the String prototype object has a `trim' property whose
> value can be type-converted to `true'.

As usually, delivering full explanation. :-)

>> Is there a way to check if (for example: String.prototype.trim) is a
>> real built-in method?
>
> No (looking for "[native code]" is _not_ reliable; function serialization is
> *implementation-dependent*), and there should not be a need for it.

I don't know better way to check if method is really built-in.

> However, you can increase the probabililty that the property (value) is
> callable, and you can handle odd cases (this may be part of a user-defined
> wrapper):
>
>    if (typeof bar.trim == "function")
>    {
>      try
>      {
>        var foo = bar.trim();
>      }
>      catch (e)
>      {
>        …
>      }
>    }
>
> try-catch might need to be guarded for a maximum of backwards-compatibility:
>
>    if (typeof bar.trim == "function")
>    {
>      eval("try { var foo = bar.trim(); }"
>         + "catch (e) { … }");
>    }

I think its not about if property (value) is callable. Even, if property 
is callable this means only that property (value) is... callable. There 
is no guarantee that property (value) will return the correct result. Right?

> See also: http://PointedEars.de/es-matrix>

I know this table.

> PointedEars

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16841

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-25 00:03 +0200
Message-ID<3102322.j8kCu7WbkW@PointedEars.de>
In reply to#16840
Cezary Tomczyk wrote:

> W dniu 2012-10-24 03:15, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
>>> I have read this article:
>>> http://perfectionkills.com/extending-built-in-native-objects-evil-or-
not/
>>>
>>> At the end there is:
>>>
>>> "[...] It should be now clear that extending native built-ins is
>>> definitely not as risky as messing with host objects. Do it carefully,
>>> follow spec closely, and use your reasonable judgement.[...]"
>>>
>>> In my project I use some of the 3-rd party library. I didn't knew that
>>> this library overwritten many of built-in native methods.
>> Do not use that library then; it is junk.  A library should only
>> overwrite
> 
> Sometimes it is just impossible. And especially you should know about
> that.

What are you getting at?  I do not use junk libraries, I strongly recommend 
against them at every opportunity, and I explain why; and I am working on 
better ones for everybody (including me) to use freely and for free, and to 
contribute to them.
 
>> Any library that provides an emulation of a built-in method should only
>> do that after it has been determined that the built-in method is
>> unavailable:
> 
> Yes, but only on one condition: if developer know how to do it in right
> way.

A developer who does not know how to do it right has failed at their job.

>>    if (typeof foo.whatever != "function")
> 
> I would use !== here. Its slightly faster than != because there is no
> type conversion.

Nonsense.  `typeof' yields a result of type String.

>>    {
>>      foo.whatever = function (…) {
>>        …
>>      };
>>    }
>>
>> or even
>>
>>    if (typeof foo.whatever != "undefined")
>>    {
>>      foo.whatever = function (…) {
>>        …
>>      };
>>    }
>>
>> `foo' should not refer to a host object then.  And whenever a built-in
>> method is overwritten by a library, it should be done so that the
>> specified way of calling that method is still supported.
> 
> But if foo.whatever is defined then I'm not sure if this foo.whatever
> working as expected. I mean, as defined in documentation. For example:
> https://developer.mozilla.org/en-
US/docs/JavaScript/Reference/Global_Objects/String/Trim

That is only the documentation of one implementation.  Refer to the 
Specification first.

> Maybe its good to write here small unit test and try to check what is
> the result from method foo.whatever. Then I can be sure if the method
> working well or not.
> 
> Am I correct?

Unit tests are always a good idea.

>>> And even worst, they work different than they should. I mean, results is
>>> not the same as expected.
>>>
>>> So, when I'm doing:
>>>
>>> if (String.prototype.trim)
>>>
>>> and its passed then this means that trim method exists.
>>
>> No, it means that the String prototype object has a `trim' property whose
>> value can be type-converted to `true'.
> 
> As usually, delivering full explanation. :-)

  String.prototype.trim = 42;

  if (String.prototype.trim)
  {
    /* TypeError */
    "foo".trim();
  }
 
>>> Is there a way to check if (for example: String.prototype.trim) is a
>>> real built-in method?
>>
>> No (looking for "[native code]" is _not_ reliable; function serialization
>> is *implementation-dependent*), and there should not be a need for it.
> 
> I don't know better way to check if method is really built-in.

A possibility is to check if the property is enumerable, because user-
defined methods tend to be enumerable, while built-in methods tend not to. 
The built-in trim() method is not enumerable.  This is easy and efficient to 
test in conforming implementations of ECMAScript Edition 5.x (provided that 
method has not been blindly overwritten too):

  if (String.prototype.propertyIsEnumerable("trim"))

The method can be emulated using a for-in loop, although the emulation will 
be enumerable by contrast to the built-in:

  if (typeof Object.prototype.propertyIsEnumerable != "function")
  {
    Object.prototype.propertyIsEnumerable = function (name) {
      for (var propertyName in this)
      {
        if (propertyName == name)
        {
          return true;
        }
      }

      return false;
    };
  }

(But it would probably be better to define it on another object to avoid 
complications with for-in.)

The caveat is that this may be not reliable.  It is possible that 
Object.defineProperty() had been used to define a non-enumerable method.

But again, why would you need to check?  Either the replacement 
implementation works *at least* as specified or it does not.  In the latter 
case either it must be considered junk and should not be used in the first 
place, or you jump through their hoops from then on and rewrite your code to 
accomodate the overwritten method instead of the behavior defined by the 
Specification.

>> However, you can increase the probabililty that the property (value) is
>> callable, and you can handle odd cases (this may be part of a
>> user-defined wrapper):
>>
>>    if (typeof bar.trim == "function")
>>    {
>>      try
>>      {
>>        var foo = bar.trim();
>>      }
>>      catch (e)
>>      {
>>        …
>>      }
>>    }
>>
>> try-catch might need to be guarded for a maximum of
>> backwards-compatibility:
>>
>>    if (typeof bar.trim == "function")
>>    {
>>      eval("try { var foo = bar.trim(); }"
>>         + "catch (e) { … }");
>>    }
> 
> I think its not about if property (value) is callable.

Yes, it is.

> Even, if property is callable this means only that property (value) is...
> callable. There is no guarantee that property (value) will return the
> correct result.
> Right?

Correct.  But you cannot test everything.

>> See also: http://PointedEars.de/es-matrix>
> 
> I know this table.

Good.  It will change considerably.

-- 
PointedEars

[toc] | [prev] | [next] | [standalone]


#16891

FromAsen Bozhilov <asen.bozhilov@gmail.com>
Date2012-10-26 03:58 -0700
Message-ID<b02b42e6-1fa8-407e-b348-52627eda24ee@q4g2000vbg.googlegroups.com>
In reply to#16841
Thomas 'PointedEars' Lahn wrote:

> A possibility is to check if the property is enumerable, because user-
> defined methods tend to be enumerable, while built-in methods tend not to.
> The built-in trim() method is not enumerable.  This is easy and efficient to
> test in conforming implementations of ECMAScript Edition 5.x (provided that
> method has not been blindly overwritten too):
>
>   if (String.prototype.propertyIsEnumerable("trim"))
>
> The method can be emulated using a for-in loop, although the emulation will
> be enumerable by contrast to the built-in:
>
>   if (typeof Object.prototype.propertyIsEnumerable != "function")
>   {
>     Object.prototype.propertyIsEnumerable = function (name) {
>       for (var propertyName in this)
>       {
>         if (propertyName == name)
>         {
>           return true;
>         }
>       }
>
>       return false;
>     };
>   }

Unfortunately there is not a way to implement shim for
`propertyIsEnumerable'. While I think you solution is right, ECMA-262
has a "bug" in `propertyIsEnumerable'. It does not consider the
prototype chain of the object. So if looking property is not an own
property, the built-in function returns false, while your version is
looking for the property in the prototype chain.

There is also a bug filled by David Flanagan:
<URL: https://bugzilla.mozilla.org/show_bug.cgi?id=57048>

Even Brandon thinks that is a bug in the specification, but someone
has "fixed" the early SpiderMonkey and leaved the specification with
that error.

[toc] | [prev] | [next] | [standalone]


#16949

FromRobG <rgqld@iinet.net.au>
Date2012-10-29 16:39 -0700
Message-ID<56c5a798-6ba5-4ff0-bcfa-dd49135d5b88@googlegroups.com>
In reply to#16891
On Friday, 26 October 2012 20:58:39 UTC+10, Asen Bozhilov  wrote:
> Thomas 'PointedEars' Lahn wrote:
> 
> > A possibility is to check if the property is enumerable, because user-
> > defined methods tend to be enumerable, while built-in methods tend not to.
> > The built-in trim() method is not enumerable.  This is easy and efficient to
> > test in conforming implementations of ECMAScript Edition 5.x (provided that
> > method has not been blindly overwritten too):
> >
> >   if (String.prototype.propertyIsEnumerable("trim"))
> >
> > The method can be emulated using a for-in loop, although the emulation will
> > be enumerable by contrast to the built-in:
> >
> >   if (typeof Object.prototype.propertyIsEnumerable != "function")
> >   {
> >     Object.prototype.propertyIsEnumerable = function (name) {
> >       for (var propertyName in this)
> >       {
> >         if (propertyName == name)

Since propertyIsEnumerable only considers own properties, that should probably be: 

            if (this.hasOwnProperty(propertyName) && propertyName == name) 

Of course if hasOwnProperty isn't implemented, life is a bit tougher.

> 
> >         {
> >           return true;
> >         }
> >       }
> >
> >       return false;
> >     };
> >   }
> 
> Unfortunately there is not a way to implement shim for
> `propertyIsEnumerable'. While I think you solution is right, ECMA-262
> has a "bug" in `propertyIsEnumerable'. It does not consider the
> prototype chain of the object. So if looking property is not an own
> property, the built-in function returns false, while your version is
> looking for the property in the prototype chain.

Doesn't the inclusion of a hasOwnProperty test overcome that? There are versions of Safari (< 2?) that don't have hasOwnProperty, propertyIsEnumerable can be used as an alternative.

And yes, it does seem illogical that the [[Prototype]] chain is ignored.

Also, it seems that __proto__ is making a comeback[1], so it might be possible to iterate over enumerable properties of an object and ignore those on the [[Prototype]] chain by comparing to the object's __proto__.

There is also the ES5 Object.getPrototypeOf[2], however it's difficult to see any implementation having getPrototypeOf or __proto__ and not having both propertyIsEnumerable and hasOwnProperty. 
 

1. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/proto

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

-- 
Rob

[toc] | [prev] | [next] | [standalone]


#16921

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-28 15:32 +0100
Message-ID<k6jfld$q6l$1@speranza.aioe.org>
In reply to#16841
W dniu 2012-10-25 00:03, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:
>
>> W dniu 2012-10-24 03:15, Thomas 'PointedEars' Lahn pisze:
>>> Cezary Tomczyk wrote:
>>>> I have read this article:
>>>> http://perfectionkills.com/extending-built-in-native-objects-evil-or-
> not/
>>>>
>>>> At the end there is:
>>>>
>>>> "[...] It should be now clear that extending native built-ins is
>>>> definitely not as risky as messing with host objects. Do it carefully,
>>>> follow spec closely, and use your reasonable judgement.[...]"
>>>>
>>>> In my project I use some of the 3-rd party library. I didn't knew that
>>>> this library overwritten many of built-in native methods.
>>> Do not use that library then; it is junk.  A library should only
>>> overwrite
>>
>> Sometimes it is just impossible. And especially you should know about
>> that.
>
> What are you getting at?  I do not use junk libraries, I strongly recommend
> against them at every opportunity, and I explain why; and I am working on
> better ones for everybody (including me) to use freely and for free, and to
> contribute to them.

It's not about me. I just can't change it.

>>> Any library that provides an emulation of a built-in method should only
>>> do that after it has been determined that the built-in method is
>>> unavailable:
>>
>> Yes, but only on one condition: if developer know how to do it in right
>> way.
>
> A developer who does not know how to do it right has failed at their job.

You never make mistakes? I don't believe in it.

>>>     if (typeof foo.whatever != "function")
>>
>> I would use !== here. Its slightly faster than != because there is no
>> type conversion.
>
> Nonsense.  `typeof' yields a result of type String.

That's weird for me. I thought that === will be much faster than == 
because there is no internal type conversion. I created the test:

http://jsperf.com/typeof-equals-triple-double

and its seems that == is even sometimes faster. But it depends on browser.

However, JSHint report me that I need replace every == by === because 
settings in JSHint require always ===. I wonder why this is required in 
our project by other developers? Correct me if I'm wrong, but if we know 
what type of object will be then there is no need to use ===, right?

>>>     {
>>>       foo.whatever = function (…) {
>>>         …
>>>       };
>>>     }
>>>
>>> or even
>>>
>>>     if (typeof foo.whatever != "undefined")
>>>     {
>>>       foo.whatever = function (…) {
>>>         …
>>>       };
>>>     }
>>>
>>> `foo' should not refer to a host object then.  And whenever a built-in
>>> method is overwritten by a library, it should be done so that the
>>> specified way of calling that method is still supported.
>>
>> But if foo.whatever is defined then I'm not sure if this foo.whatever
>> working as expected. I mean, as defined in documentation. For example:
>> https://developer.mozilla.org/en-
> US/docs/JavaScript/Reference/Global_Objects/String/Trim
>
> That is only the documentation of one implementation.  Refer to the
> Specification first.

You mean this one: 
http://ecma-international.org/ecma-262/5.1/#sec-15.5.4.20 ?

>> Maybe its good to write here small unit test and try to check what is
>> the result from method foo.whatever. Then I can be sure if the method
>> working well or not.
>>
>> Am I correct?
>
> Unit tests are always a good idea.

Of course.

>>>> And even worst, they work different than they should. I mean, results is
>>>> not the same as expected.
>>>>
>>>> So, when I'm doing:
>>>>
>>>> if (String.prototype.trim)
>>>>
>>>> and its passed then this means that trim method exists.
>>>
>>> No, it means that the String prototype object has a `trim' property whose
>>> value can be type-converted to `true'.
>>
>> As usually, delivering full explanation. :-)
>
>    String.prototype.trim = 42;
>
>    if (String.prototype.trim)
>    {
>      /* TypeError */
>      "foo".trim();
>    }

That's possible. Then we should here check if String.prototype.trim is a 
function, right?

>>>> Is there a way to check if (for example: String.prototype.trim) is a
>>>> real built-in method?
>>>
>>> No (looking for "[native code]" is _not_ reliable; function serialization
>>> is *implementation-dependent*), and there should not be a need for it.
>>
>> I don't know better way to check if method is really built-in.
>
> A possibility is to check if the property is enumerable, because user-
> defined methods tend to be enumerable, while built-in methods tend not to.
> The built-in trim() method is not enumerable.  This is easy and efficient to
> test in conforming implementations of ECMAScript Edition 5.x (provided that
> method has not been blindly overwritten too):
>
>    if (String.prototype.propertyIsEnumerable("trim"))
>
> The method can be emulated using a for-in loop, although the emulation will
> be enumerable by contrast to the built-in:
>
>    if (typeof Object.prototype.propertyIsEnumerable != "function")
>    {
>      Object.prototype.propertyIsEnumerable = function (name) {
>        for (var propertyName in this)
>        {
>          if (propertyName == name)
>          {
>            return true;
>          }
>        }
>
>        return false;
>      };
>    }
>
> (But it would probably be better to define it on another object to avoid
> complications with for-in.)
>
> The caveat is that this may be not reliable.  It is possible that
> Object.defineProperty() had been used to define a non-enumerable method.
>
> But again, why would you need to check?  Either the replacement
> implementation works *at least* as specified or it does not.  In the latter
> case either it must be considered junk and should not be used in the first
> place, or you jump through their hoops from then on and rewrite your code to
> accomodate the overwritten method instead of the behavior defined by the
> Specification.

Thanks for explanation.

However, as for question "why I need to check it?". Reason is simple: 
library, which is included in project, have a few methods (not only 
"trim") that are very badly implemented. Trim is just one of them.

What I want to get? I want to use built-in trim method only if it is 
really built-in or use my custom trim method. Because trim that coming 
from external library (by extending native built-in object String) is 
badly implemented.

>>> However, you can increase the probabililty that the property (value) is
>>> callable, and you can handle odd cases (this may be part of a
>>> user-defined wrapper):
>>>
>>>     if (typeof bar.trim == "function")
>>>     {
>>>       try
>>>       {
>>>         var foo = bar.trim();
>>>       }
>>>       catch (e)
>>>       {
>>>         …
>>>       }
>>>     }
>>>
>>> try-catch might need to be guarded for a maximum of
>>> backwards-compatibility:
>>>
>>>     if (typeof bar.trim == "function")
>>>     {
>>>       eval("try { var foo = bar.trim(); }"
>>>          + "catch (e) { … }");
>>>     }
>>
>> I think its not about if property (value) is callable.
>
> Yes, it is.

After study your example more closely then I must say: you were right.

>> Even, if property is callable this means only that property (value) is...
>> callable. There is no guarantee that property (value) will return the
>> correct result.
>> Right?
>
> Correct.  But you cannot test everything.

That's true.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16923

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-28 17:05 +0100
Message-ID<1886339.7pA5ev5edD@PointedEars.de>
In reply to#16921
Cezary Tomczyk wrote:

> W dniu 2012-10-25 00:03, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
>>> W dniu 2012-10-24 03:15, Thomas 'PointedEars' Lahn pisze:
>>>> Cezary Tomczyk wrote:
>>>>> I have read this article:
>>>>> http://perfectionkills.com/extending-built-in-native-objects-evil-or-
>>>>> not/
>>>>>
>>>>> At the end there is:
>>>>>
>>>>> "[...] It should be now clear that extending native built-ins is
>>>>> definitely not as risky as messing with host objects. Do it carefully,
>>>>> follow spec closely, and use your reasonable judgement.[...]"
>>>>>
>>>>> In my project I use some of the 3-rd party library. I didn't knew that
>>>>> this library overwritten many of built-in native methods.
>>>> Do not use that library then; it is junk.  A library should only
>>>> overwrite
>>> Sometimes it is just impossible. And especially you should know about
>>> that.
>>
>> What are you getting at?  I do not use junk libraries, I strongly
>> recommend against them at every opportunity, and I explain why; and I am
>> working on better ones for everybody (including me) to use freely and for
>> free, and to contribute to them.
> 
> It's not about me. I just can't change it.

Yes, you can.
 
>>>> Any library that provides an emulation of a built-in method should only
>>>> do that after it has been determined that the built-in method is
>>>> unavailable:
>>>
>>> Yes, but only on one condition: if developer know how to do it in right
>>> way.
>>
>> A developer who does not know how to do it right has failed at their job.
> 
> You never make mistakes? I don't believe in it.

Everybody makes mistakes; we can learn from them to make it better next 
time.  But making mistakes because of overlooking some detail, and making 
mistakes because one does not know what they are doing in the first place, 
are very different things.  You *know* now that you have made a mistake by 
either participating in a bad project, using a bad library, or both; not 
correcting it now would be yet another mistake on your part.
 
>>>>     if (typeof foo.whatever != "function")
>>>
>>> I would use !== here. Its slightly faster than != because there is no
>>> type conversion.
>>
>> Nonsense.  `typeof' yields a result of type String.
> 
> That's weird for me. I thought that === will be much faster than ==
> because there is no internal type conversion.

This should be self-evident: There is no type conversion when both operands 
are of the same type.  See also ES 5.1, §11.9.

> I created the test:
> 
> http://jsperf.com/typeof-equals-triple-double
> 
> and its seems that == is even sometimes faster. But it depends on browser.
> 
> However, JSHint report me that I need replace every == by === because
> settings in JSHint require always ===.

Delete JSHint.

> I wonder why this is required in our project by other developers?

I do not know.  Perhaps because they cannot deal with type conversion as 
they are used to statically and strictly typed languages?  Very few people 
actually understand these languages and their applications, which accounts 
for a lot of bad code written in them.

> Correct me if I'm wrong, but if we know what type of object will be then
> there is no need to use ===, right?

No, it depends on the operands, and it depends on whether the operands are 
object (reference)s to begin with.  Neither a `typeof' operation nor 
evaluating a string literal results in an object (reference).

>>>>     {
>>>>       foo.whatever = function (…) {
>>>>         …
>>>>       };
>>>>     }
>>>>
>>>> or even
>>>>
>>>>     if (typeof foo.whatever != "undefined")
>>>>     {
>>>>       foo.whatever = function (…) {
>>>>         …
>>>>       };
>>>>     }
>>>>
>>>> `foo' should not refer to a host object then.  And whenever a built-in
>>>> method is overwritten by a library, it should be done so that the
>>>> specified way of calling that method is still supported.
>>>
>>> But if foo.whatever is defined then I'm not sure if this foo.whatever
>>> working as expected. I mean, as defined in documentation. For example:
>>> https://developer.mozilla.org/en-
>> US/docs/JavaScript/Reference/Global_Objects/String/Trim
>>
>> That is only the documentation of one implementation.  Refer to the
>> Specification first.
> 
> You mean this one:
> http://ecma-international.org/ecma-262/5.1/#sec-15.5.4.20 ?

Yes.
 
>>>>> So, when I'm doing:
>>>>>
>>>>> if (String.prototype.trim)
>>>>>
>>>>> and its passed then this means that trim method exists.
>>>>
>>>> No, it means that the String prototype object has a `trim' property
>>>> whose value can be type-converted to `true'.
>>>
>>> As usually, delivering full explanation. :-)
>>
>>    String.prototype.trim = 42;
>>
>>    if (String.prototype.trim)
>>    {
>>      /* TypeError */
>>      "foo".trim();
>>    }
> 
> That's possible. Then we should here check if String.prototype.trim is a
> function, right?

Yes.  The call may still fail in some cases, but you would have done your 
best to prevent it.  This is what defensive coding is about.
 
> However, as for question "why I need to check it?". Reason is simple:
> library, which is included in project, have a few methods (not only
> "trim") that are very badly implemented. Trim is just one of them.

So, assuming you are a responsible developer and a responsible person in 
general, you should ask yourself: Why is this project using bad code now?  
And why do you want to keep on using bad code in your project?  Does that 
not inevitably make *your* (project's) code bad code as well?  Consider the 
repercussions of (your) design decisions.
 
> What I want to get? I want to use built-in trim method only if it is
> really built-in or use my custom trim method. Because trim that coming
> from external library (by extending native built-in object String) is
> badly implemented.

I have already told you what your options are at this point:

A. You can stop using that library (and perhaps use a better one);
B. You can fix the library;
C. You can demand a fix from its author(s).

I do not think there are other options.

-- 
PointedEars

[toc] | [prev] | [next] | [standalone]


#16927

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-28 18:39 +0100
Message-ID<k6jqlh$nlb$1@speranza.aioe.org>
In reply to#16923
W dniu 2012-10-28 17:05, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:

>>>>> Any library that provides an emulation of a built-in method should only
>>>>> do that after it has been determined that the built-in method is
>>>>> unavailable:
>>>>
>>>> Yes, but only on one condition: if developer know how to do it in right
>>>> way.
>>>
>>> A developer who does not know how to do it right has failed at their job.
>>
>> You never make mistakes? I don't believe in it.
>
> Everybody makes mistakes; we can learn from them to make it better next
> time.  But making mistakes because of overlooking some detail, and making
> mistakes because one does not know what they are doing in the first place,
> are very different things.  You *know* now that you have made a mistake by

That's why in my job I always asking other developers: "why did you do 
in that way?". If developer can explain in a clear way, I mean in that 
way I can understand, will provide me real example as a evidence and 
eventually source of algorithm (or idea) then working in that way for me 
is best optimized.

> either participating in a bad project, using a bad library, or both; not
> correcting it now would be yet another mistake on your part.

Well, then there is at least few options:

1. Try to find the right people for change.
2. Accept the situation as it is and try to create a solution that will 
protect against errors of others.
3. Change project.
4. Build own project.

>>>>>      if (typeof foo.whatever != "function")
>>>>
>>>> I would use !== here. Its slightly faster than != because there is no
>>>> type conversion.
>>>
>>> Nonsense.  `typeof' yields a result of type String.
>>
>> That's weird for me. I thought that === will be much faster than ==
>> because there is no internal type conversion.
>
> This should be self-evident: There is no type conversion when both operands
> are of the same type.  See also ES 5.1, §11.9.

I even extended little bit this test 
http://jsperf.com/typeof-equals-triple-double by comparing two different 
objects and IE9, Google Chrome 22.0.1229.94, Opera 12.02 for 4 tests are 
more or less similar, but Firefox 16.0.2 surprised me little bit:

triple equals: 8167 Ops/sec
double equals: 4752 Ops/sec
triple equals - different objects: 90830 Ops/sec
double equals - different objects: 89815 Ops/sec

All of them tested on Windows 7, 64 bit.

What a huge difference. Weird for me, little bit.

>> I created the test:
>>
>> http://jsperf.com/typeof-equals-triple-double
>>
>> and its seems that == is even sometimes faster. But it depends on browser.
>>
>> However, JSHint report me that I need replace every == by === because
>> settings in JSHint require always ===.
>
> Delete JSHint.

Not all options are bad, I would say. Sometimes it prevent from a small, 
but very important bugs.

>> Correct me if I'm wrong, but if we know what type of object will be then
>> there is no need to use ===, right?
>
> No, it depends on the operands, and it depends on whether the operands are
> object (reference)s to begin with.  Neither a `typeof' operation nor
> evaluating a string literal results in an object (reference).

I thought about situation where both of operands are the same type.

I've just reviewed my bookmarks and see nice article: 
http://dmitrysoshnikov.com/notes/note-2-ecmascript-equality-operators/#safe-cases-of-codecode.

"The main thing which you should know that algorithms of == and === 
operator are completely equivalent, word-for-word, if types of operands 
are the same."

>> However, as for question "why I need to check it?". Reason is simple:
>> library, which is included in project, have a few methods (not only
>> "trim") that are very badly implemented. Trim is just one of them.
>
> So, assuming you are a responsible developer and a responsible person in
> general, you should ask yourself: Why is this project using bad code now?
> And why do you want to keep on using bad code in your project?  Does that
> not inevitably make *your* (project's) code bad code as well?  Consider the
> repercussions of (your) design decisions.

It's not my decision. It is required by project on which I'm co-working 
now. This project depend on 3-rd parties. Anyway, I've got your point, I 
understand and even know what consequences will be in the future, but 
let's no talk about situations that I cannot change.

>> What I want to get? I want to use built-in trim method only if it is
>> really built-in or use my custom trim method. Because trim that coming
>> from external library (by extending native built-in object String) is
>> badly implemented.
>
> I have already told you what your options are at this point:
>
> A. You can stop using that library (and perhaps use a better one);
> B. You can fix the library;
> C. You can demand a fix from its author(s).
>
> I do not think there are other options.

For now I must work with option B (by wrapping bad methods with my 
custom methods as a temporary workaround) and count on fixes from point C.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16932

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-28 20:10 +0100
Message-ID<270317591.RgZlF00zI7@PointedEars.de>
In reply to#16927
Cezary Tomczyk wrote:

> I even extended little bit this test
> http://jsperf.com/typeof-equals-triple-double by comparing two different
> objects and IE9, Google Chrome 22.0.1229.94, Opera 12.02 for 4 tests are
> more or less similar, but Firefox 16.0.2 surprised me little bit:
> 
> triple equals: 8167 Ops/sec
> double equals: 4752 Ops/sec
> triple equals - different objects: 90830 Ops/sec
> double equals - different objects: 89815 Ops/sec
> 
> All of them tested on Windows 7, 64 bit.
> 
> What a huge difference. Weird for me, little bit.

1. You are benchmarking the wrong feature there.
2. I do not think you need loops with jsperf.
3. Never trust benchmarks.
 

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$8300dec7@news.demon.co.uk>

[toc] | [prev] | [next] | [standalone]


#16933

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-10-28 20:23 +0100
Message-ID<k6k0n0$8eb$1@speranza.aioe.org>
In reply to#16932
W dniu 2012-10-28 20:10, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:
>
>> I even extended little bit this test
>> http://jsperf.com/typeof-equals-triple-double by comparing two different
>> objects and IE9, Google Chrome 22.0.1229.94, Opera 12.02 for 4 tests are
>> more or less similar, but Firefox 16.0.2 surprised me little bit:
>>
>> triple equals: 8167 Ops/sec
>> double equals: 4752 Ops/sec
>> triple equals - different objects: 90830 Ops/sec
>> double equals - different objects: 89815 Ops/sec
>>
>> All of them tested on Windows 7, 64 bit.
>>
>> What a huge difference. Weird for me, little bit.
>
> 1. You are benchmarking the wrong feature there.

Ok, maybe I should do two separate tests.

> 2. I do not think you need loops with jsperf.

Is there better way?

> 3. Never trust benchmarks.

Then one of the alternative is to measure time by using new 
Date().getTime() :/

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#16935

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-28 21:23 +0100
Message-ID<1626770.WBuXB4FIxE@PointedEars.de>
In reply to#16933
Cezary Tomczyk wrote:

> W dniu 2012-10-28 20:10, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
>>> I even extended little bit this test
>>> http://jsperf.com/typeof-equals-triple-double by comparing two different
>>> objects and IE9, Google Chrome 22.0.1229.94, Opera 12.02 for 4 tests are
>>> more or less similar, but Firefox 16.0.2 surprised me little bit:
>>>
>>> triple equals: 8167 Ops/sec
>>> double equals: 4752 Ops/sec
>>> triple equals - different objects: 90830 Ops/sec
>>> double equals - different objects: 89815 Ops/sec
>>>
>>> All of them tested on Windows 7, 64 bit.
>>>
>>> What a huge difference. Weird for me, little bit.
>>
>> 1. You are benchmarking the wrong feature there.
> 
> Ok, maybe I should do two separate tests.

You wanted to test `==' vs. `==='.  What you are actually testing there is 
`typeof ""' vs. `typeof {}'.  Keep in mind that the `typeof' operation 
*always* results in a string value.

>> 2. I do not think you need loops with jsperf.
> 
> Is there better way?

Yes, omit them.  jsperf loops by itself, and if it is any good it uses 
nested loops.

>> 3. Never trust benchmarks.
> 
> Then one of the alternative is to measure time by using new
> Date().getTime() :/

No, the reasonable alternative is to profile real code under real conditions 
if and when slow speed becomes a problem.  A V8 JavaScript profiler is 
included in the Chromium/Chrome Developer Tools; Firebug contains one for 
SpiderMonkey as well.  Premature optimization is the root of all evil. [tm]

The issue of `==' vs. `===' is not so much speed; it is the outcome of 
either operation, which can be unexpected in the former case.


PointedEars
-- 
Sometimes, what you learn is wrong. If those wrong ideas are close to the 
root of the knowledge tree you build on a particular subject, pruning the 
bad branches can sometimes cause the whole tree to collapse.
  -- Mike Duffy in cljs, <news:Xns9FB6521286DB8invalidcom@94.75.214.39>

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.javascript


csiph-web