Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #12832
| Message-ID | <1795217.bUTGlsRvRN@PointedEars.de> (permalink) |
|---|---|
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
| Organization | PointedEars Software (PES) |
| Date | 2012-03-17 00:10 +0100 |
| 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 |
Followups directed to: comp.lang.javascript
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
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