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


Groups > comp.lang.javascript > #12832

Re: Adding new method to existing object

Path csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!news.teledata-fn.de!newsfeed.arcor.de!newsspool3.arcor-online.net!news.arcor.de.POSTED!not-for-mail
Content-Type text/plain; charset="UTF-8"
Message-ID <1795217.bUTGlsRvRN@PointedEars.de> (permalink)
From Thomas 'PointedEars' Lahn <PointedEars@web.de>
Reply-To Thomas 'PointedEars' Lahn <cljs@PointedEars.de>
Organization PointedEars Software (PES)
Date Sat, 17 Mar 2012 00:10:38 +0100
User-Agent KNode/4.4.11
Content-Transfer-Encoding 8Bit
Subject Re: Adding new method to existing object
Newsgroups comp.lang.javascript
References <31786995.22.1331895413978.JavaMail.geo-discussion-forums@vbat19> <571e5767-fc18-4945-b356-4004af1145e8@q12g2000yqg.googlegroups.com> <7404478.9nW1t498yI@PointedEars.de> <ee3d3a2a-9711-425a-a151-cba30d66b41f@g16g2000yqe.googlegroups.com>
Followup-To comp.lang.javascript
MIME-Version 1.0
Lines 165
NNTP-Posting-Date 17 Mar 2012 00:10:39 CET
NNTP-Posting-Host 5275392c.newsspool4.arcor-online.net
X-Trace DXC=Wn3]lccZlPdEB;5>eE0T7m4IUK<Cl32<a4Fo<]lROoRa8kF<OcfhCOkOSYjad_SmciDZm8W4\YJNlb@mF9jNikdeM88iJ]<ZLbj<1cB<bXU>ha
X-Complaints-To usenet-abuse@arcor.de
Xref csiph.com comp.lang.javascript:12832

Followups directed to: comp.lang.javascript

Show key headers only | View raw


David Mark wrote:

> Thomas 'PointedEars' Lahn wrote:
>> A property is resolved against the prototype chain only on property
>> access.
> 
> Yes.  And calling a method on an object applies.

Exactly.

>> Therefore, if you augment the prototype of the constructor of an object,
>> that affects all objects created with that constructor (no matter the
>> current value of the `constructor' property), no matter when they have
>> been constructed.
> 
> I was mistaken; I don't use the constructor property for much of
> anything (it's pretty useless). *If* that property hasn't been stomped
> on at some point, it references the function used to construct the
> object. I had it in my head that the prototype property of that object
> references an object that was copied *once* and put at the head of the
> prototype chain on constructing the object. From what you are saying,
> it isn't copied but referenced where it sits.

Yes, as it is the case with ECMAScript implementations most of the time 
(always with this property).

>> It is why augmenting `Object.prototype', no matter where in the program,
>> can be that harmful to program flow if appropriate precautions have not
>> been taken.
> 
> I don't do that under any circumstances. :)

Certainly a good idea until ECMAScript Edition 5 has been widely adopted, 
where one can define properties as not enumerable, for example:

  Object.defineProperty(Object.prototype, "foo", {
    value: 42,
    writable: true
  });

(The defaults are value === undefined, enumerable === false, writable === 
false, configurable === false, i.e.

  Object.defineProperty(Object.prototype, "foo", {});

creates a not enumerable, "eternally" frozen property on the Object 
prototype object with value `undefined'.  In that sense,

  Object.defineProperty(Object.prototype, "answer", {value: 42});

would be the ultimate achievement ;-))

>> There is no difference between ECMAScript implementations there.
>>
>> function Constructor() {}
>>
>> var obj = new Constructor();
>>
>> Constructor.prototype.answer = 42;
>>
>> /* 42 */
>> console.log(obj.answer);
> 
> Yes, I see that works; so clearly I was wrong. Regardless, that's an
> execrable pattern and certainly not one that I would use. Any project
> that did something like that would be re-factored long before I ran it
> for the first time. :)

It is a potentially useful pattern if you consider that primitive values are 
internally converted to corresponding objects if they are used in a 
/MemberExpression/.  For example, I can see no harm in writing

  String.prototype.htmlEscape = function () {
    return this.replace(/[\u0080-\uFFFF]/g, function (m) {
      return "&#" + m.charCodeAt(0) + ";";
    });
  };

  console.log("|@#°½¬¦¢øĸjħŋđδ".htmlEscape());

  /* optional */
  delete String.prototype.htmlEscape;

instead of

  var htmlEscape = function (s) {
    return s.replace(/[\u0080-\uFFFF]/g, function (m) {
      return "&#" + m.charCodeAt(0) + ";";
    });
  };

  console.log(htmlEscape("|@#°½¬¦¢øĸjħŋđδ"));

The advantage of augmenting built-in prototype objects is that if the new 
property is callable, you can use in the method all the properties in the 
prototype chain without having to use another wrapper explicitly.  The 
disadvantage is that name of the custom property might clash with built-in 
property names, and that (in implementations of ECMAScript before Edition 5) 
they must show up in for-in iteration.

> Ah, right.  This works too:-
> 
> function Constructor() { Constructor.prototype.answer = 42; }
>   var obj = new Constructor();
> 
>   /* 42 */
>   console.log(obj.answer);
> 
> I was thinking of *replacing* the prototype object, rather than
> augmenting it. Never made the distinction as I try not to think about
> things I would never do (or would let stand if somebody else did it).

That example shows an approach for another potentially useful pattern, too, 
where prototype methods close over arguments or local variables, creating 
"private properties" accessible by inheritable "protected methods":

  function Constructor (answer)
  {
    Constructor.prototype.getAnswer = function () {
      return answer;
    };
  }

  var obj = new Constructor();

  /* 42 */
  obj.getAnswer();  

(The reduced memory efficiency can be mitigated with slightly reduced 
runtime efficiency if the property is tested before the function is created 
and a reference to it assigned, so that this only happen twice if someone 
has messed with the prototype in the meantime.)

There is another way to do a similar thing, though (quite clever, not my 
idea):

  function Constructor () {}

  Constructor.prototype = (function () {
    var privatePrototypeProperty = 42;

    return {
      constructor: Constructor,

      prototypeMethod: function () {
        return privatePrototypeProperty;
      }
    };
  }());

  var obj = new Constructor();

  /* 42 */
  obj.prototypeMethod();  

The difference is that the second "private property" is prototype-based, 
while the first one is instance-based.


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

Back to comp.lang.javascript | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-16 03:56 -0700
  Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-16 04:50 -0700
    Re: Adding new method to existing object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-03-16 15:31 +0100
      Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-16 11:51 -0700
        Re: Adding new method to existing object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-03-17 00:10 +0100
          Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-16 17:25 -0700
            Re: Adding new method to existing object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-03-17 02:04 +0100
              Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-16 18:15 -0700
    Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-16 10:18 -0700
      Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-16 11:56 -0700
      Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-16 13:01 -0700
        Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-17 04:58 -0700
          Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-17 16:04 -0700
            Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-18 04:24 -0700
              Re: Adding new method to existing object John G Harris <john@nospam.demon.co.uk> - 2012-03-18 13:16 +0000
  Re: Adding new method to existing object John G Harris <john@nospam.demon.co.uk> - 2012-03-16 17:09 +0000
    Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-16 10:46 -0700
  Re: Adding new method to existing object Scott Sauyet <scott.sauyet@gmail.com> - 2012-03-16 13:43 -0700
  Re: Adding new method to existing object Scott Sauyet <scott.sauyet@gmail.com> - 2012-03-16 20:15 -0700
    Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-17 05:17 -0700
    Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-17 05:24 -0700
      Re: Adding new method to existing object David Mark <dmark.cinsoft@gmail.com> - 2012-03-17 16:16 -0700
        Re: Adding new method to existing object cezary.tomczyk@gmail.com - 2012-03-18 04:27 -0700

csiph-web