By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,712 Members | 1,381 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,712 IT Pros & Developers. It's quick & easy.

Defining a property with the DontEnum attribute

P: n/a
All --

I'm trying to solve a problem for which I think the solution will be
to *cheat*; but I don't mind doing so for this case. The background is:

Given an object constructor, and an instance

SampleObj = function() {
this.prop = 1;
}
obj = new SampleObj();
obj has one enumerable property: 'prop'; and several builtin,
non-enumerable properties as well: 'toString', 'hasOwnProperty',
'propertyIsEnumerable', etc. If I redefined any of those, e.g:

SampleObj.prototype.toString = function() {return '[SampleObj]'};

then obj still has only one enumerable property; the redefinition of
toString doesn't affect its "DontEnum"-ness.

I'd like to be able to create such a property from JavaScript. In
particular, in older versions of Safari, some of those required properties
aren't implemented (hasOwnProperty, isPrototypeOf, propertyIsEnumerable,
& toLocaleString). If I define them myself:

Object.prototype.toLocaleString = Object.prototype.toString;
[etc.]

then they are enumerable, which causes problems for code like

for (var prop in obj) ...

I'll get a different set of enumerated properties in Safari than in (e.g.)
Mozilla; and have to specifically check for those that I defined myself,
to make code work appropriately on each browser. This gets tricky
(considering that the old Safari versions also failed to implement
toExponential, toFixed and toPrecision for Number objects).

The ability to set the DontEnum and ReadOnly attributes of object
properties would have been great; but (afaik) there is no way to do so. So
I'm looking for a "backdoor" in Safari that would allow this.

Help anyone?
Howard Jess
Nov 23 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
VK

Howard Jess wrote:
All --

I'm trying to solve a problem for which I think the solution will be
to *cheat*; but I don't mind doing so for this case. The background is:

Given an object constructor, and an instance

SampleObj = function() {
this.prop = 1;
}
obj = new SampleObj();
obj has one enumerable property: 'prop'; and several builtin,
non-enumerable properties as well: 'toString', 'hasOwnProperty',
'propertyIsEnumerable', etc. If I redefined any of those, e.g:

SampleObj.prototype.toString = function() {return '[SampleObj]'};

then obj still has only one enumerable property; the redefinition of
toString doesn't affect its "DontEnum"-ness.

I'd like to be able to create such a property from JavaScript. In
particular, in older versions of Safari, some of those required properties
aren't implemented (hasOwnProperty, isPrototypeOf, propertyIsEnumerable,
& toLocaleString). If I define them myself:

Object.prototype.toLocaleString = Object.prototype.toString;
[etc.]

then they are enumerable, which causes problems for code like

for (var prop in obj) ...

I'll get a different set of enumerated properties in Safari than in (e.g.)
Mozilla; and have to specifically check for those that I defined myself,
to make code work appropriately on each browser. This gets tricky
(considering that the old Safari versions also failed to implement
toExponential, toFixed and toPrecision for Number objects).

The ability to set the DontEnum and ReadOnly attributes of object
properties would have been great; but (afaik) there is no way to do so. So
I'm looking for a "backdoor" in Safari that would allow this.

Help anyone?


if ("propertyName" in myObject)
gives you [true] if propertyName is presented either in the object
itself or anywhere in its prototype chain ab obo.

if (myObject.hasOwnProperty("propertyName"))
gives you [true] only if propertyName is presented in the object itself
(prototype chain is disregarded)

So it is rather simple task. But if under "older Safari" you mean
anything below 2.0 then I dubt very much that these methods are
presented themselve - and even if they are - that they will work as
they should.
Safari 1.x series can barely recognize HTML itself, what
hasOwnProperty, forget it! :-)
You may try anyway.

Nov 23 '05 #2

P: n/a
Howard Jess wrote:
SampleObj = function() {
this.prop = 1;
}
obj = new SampleObj();
obj has one enumerable property: 'prop'; and several builtin,
non-enumerable properties as well: 'toString', 'hasOwnProperty',
'propertyIsEnumerable', etc. If I redefined any of those, e.g:

SampleObj.prototype.toString = function() {return '[SampleObj]'};

then obj still has only one enumerable property; the redefinition of
toString doesn't affect its "DontEnum"-ness.

I'd like to be able to create such a property from JavaScript.
You cannot do this.
[...]
The ability to set the DontEnum and ReadOnly attributes of object
properties would have been great; but (afaik) there is no way to
do so. So I'm looking for a "backdoor" in Safari that would allow
this.


As for DontEnum:

Object.prototype.toLocaleString.dontEnum = true;

for (var foo in obj)
{
if (!obj[foo].dontEnum)
{
// ...
}
}

Should work everywhere, not only in Safari.

As for ReadOnly, there is no way to implement something
alike in JavaScript < 2.0/JScript < 7.0/ECMAScript < 4.
HTH

PointedEars
Nov 23 '05 #3

P: n/a
Thomas 'PointedEars' Lahn wrote:
SampleObj = function() {
this.prop = 1;
}
obj = new SampleObj();
obj has one enumerable property: 'prop'; and several builtin,
non-enumerable properties as well: 'toString', 'hasOwnProperty',
'propertyIsEnumerable', etc. If I redefined any of those, e.g: [snip]
I'd like to be able to create such a property from JavaScript.
You cannot do this.


Yes, as I say right here:
[...]
The ability to set the DontEnum and ReadOnly attributes of object
properties would have been great; but (afaik) there is no way to
do so. So I'm looking for a "backdoor" in Safari that would allow
this.

By "backdoor", I mean some unorthodox, undocumented hook into Safari's
JS engine. I understand that this is not possible per the spec.
As for DontEnum:

Object.prototype.toLocaleString.dontEnum = true;

for (var foo in obj)
{
if (!obj[foo].dontEnum)
{
// ...
}
}

Should work everywhere, not only in Safari.


Yes, of course, if I want to change *every* "for .. in" loop in every
piece of JavaScript code I deal with; but this is still unsatisfactory;
the "dontEnum" property you propose is itself now an enumerable property
of toLocaleString.

To repeat: I'm looking for a "backdoor", "cheat", "hook" (invent your
own term) to allow a property that I define to be non-enumerable.

hj
Nov 23 '05 #4

P: n/a
Howard Jess wrote:
Thomas 'PointedEars' Lahn wrote:
[...]
The ability to set the DontEnum and ReadOnly attributes of object
properties would have been great; but (afaik) there is no way to
do so. So I'm looking for a "backdoor" in Safari that would allow
this.

By "backdoor", I mean some unorthodox, undocumented hook into Safari's
JS engine. I understand that this is not possible per the spec.
[...]
Yes, of course, if I want to change *every* "for .. in" loop in every
piece of JavaScript code I deal with; but this is still unsatisfactory;


Tough luck.
the "dontEnum" property you propose is itself now an enumerable property
of toLocaleString.
True. Why would that pose a problem in the specific case?
To repeat: I'm looking for a "backdoor", "cheat", "hook" (invent your
own term) to allow a property that I define to be non-enumerable.


Write your own script engine and call the UA that uses it "Safari" :)

Seriously, I do not understand why anyone would need this, so I did
not gave it any thought. That said, Safari uses KJS which is Open
Source software. You could dig through the source code to find a
leak. I do not know one, and I do think this is hardly on-topic here.
PointedEars
Nov 23 '05 #5

P: n/a
Howard Jess wrote:
Thomas 'PointedEars' Lahn wrote:

SampleObj = function() {
this.prop = 1;
}
obj = new SampleObj();
obj has one enumerable property: 'prop'; and several builtin,
non-enumerable properties as well: 'toString', 'hasOwnProperty',
'propertyIsEnumerable', etc. If I redefined any of those, e.g:
[snip]
I'd like to be able to create such a property from JavaScript.


You cannot do this.

Yes, as I say right here:
[...]
The ability to set the DontEnum and ReadOnly attributes of object
properties would have been great; but (afaik) there is no way to
do so. So I'm looking for a "backdoor" in Safari that would allow
this.

By "backdoor", I mean some unorthodox, undocumented hook into Safari's
JS engine. I understand that this is not possible per the spec.

As for DontEnum:

Object.prototype.toLocaleString.dontEnum = true;

for (var foo in obj)
{
if (!obj[foo].dontEnum)
{
// ...
}
}

Should work everywhere, not only in Safari.

Yes, of course, if I want to change *every* "for .. in" loop in every
piece of JavaScript code I deal with; but this is still unsatisfactory;
the "dontEnum" property you propose is itself now an enumerable property
of toLocaleString.

To repeat: I'm looking for a "backdoor", "cheat", "hook" (invent your
own term) to allow a property that I define to be non-enumerable.


Sometimes it is better to describe more generally what you are trying to
do, rather be specific about a particular solution. Asking for hacks
into a specific JS implementation is unlikely to be answered in a public
forum - though Apple may be keen to encourage responses :-)

You could put your values into a data object inside your object (kinda
like a data fork in older Mac-speak):

SampleObj = function() {
this.data = {};
this.data.prop = 1;
}
obj = new SampleObj();

for (prop in obj.data) {
// ...
}

--
Rob
Nov 23 '05 #6

P: n/a
Rob --
I'd like to be able to create such a property from JavaScript.


To repeat: I'm looking for a "backdoor", "cheat", "hook" (invent your
own term) to allow a property that I define to be non-enumerable.


Sometimes it is better to describe more generally what you are trying to
do, rather be specific about a particular solution. Asking for hacks
into a specific JS implementation is unlikely to be answered in a public
forum - though Apple may be keen to encourage responses :-)

You could put your values into a data object inside your object (kinda
like a data fork in older Mac-speak):

SampleObj = function() {
this.data = {};
this.data.prop = 1;
}
obj = new SampleObj();

for (prop in obj.data) {
// ...
}


Fair enough. I have a code library that corrects some browsers's Javascript
misbehavior, and implements missing features. E.g.

var sel = document.createElement('select');
var opt = document.createElement('option');
sel.add(opt,null);

This doesn't work as is on Internet Explorer (which expects either a
single argument, or an index rather than an object reference for the second
argument); the library (with some help) makes it work.

Similarly,

var obj = {thing:1, otherThing:'abc'};
if (obj.hasOwnProperty('lastThing')) ...

doesn't work in Safari 1.2: that browser doesn't implement hasOwnProperty,
among others.

It's simple enough to implement it and the rest; e.g.:

Object.prototype.hasOwnProperty = function(propName) {
...
}

But in a library, I have no control over user code. And defining it
this way breaks every "for .. in" loop, whose code now must be aware
of the hasOwnProperty in -every- object. *THAT'S* why I'd like to be
able to define a new "DontEnum" property. And yes, I understand it's
not possible in standard JavaScript, and yes, I've begun looking
through the sources; I was hoping someone who frequents this group may
have some insight that might save me some time.

Thanks for any help or suggestions.
hj
Nov 24 '05 #7

P: n/a
Howard Jess wrote:
Rob --
Instead of strangely addressing people directly when posting in
an m:n medium like Usenet where everybody may read and post, you
should provide attribution of quoted material and trim your
quotes as described in <jibbering.com/faq/faq_notes/pots1.html>.
[...] I have a code library that corrects some browsers's
Javascript misbehavior, and implements missing features. E.g.

var sel = document.createElement('select');
var opt = document.createElement('option');
sel.add(opt,null);

This doesn't work as is on Internet Explorer (which expects either a
single argument, or an index rather than an object reference for the
second argument); the library (with some help) makes it work.
Why,

sel.options[sel.options.length] = new Option(...);

from DOM Level 0 still suffices everywhere and every time, so there is
no need for "repair". Please, prove me wrong.
Similarly,

var obj = {thing:1, otherThing:'abc'};
if (obj.hasOwnProperty('lastThing')) ...

doesn't work in Safari 1.2: that browser doesn't implement hasOwnProperty,
among others.
So? Beyond my ObjectInspector, I cannot think of a single instance where
it was needed to use hasOwnProperty(). Testing with simple conditional
expressions and the `typeof' operator has sufficed in all other cases.
Especially for methods, where hasOwnProperty() does not suffice to
determine if there is a high probability that the property can be called;
I'd like to have a hasOwnMethod() but there is no such method.
It's simple enough to implement it and the rest; e.g.:

Object.prototype.hasOwnProperty = function(propName) {
...
}

But in a library, I have no control over user code.
That is something you have to be aware of when coding for a host
environment. No surprise here.
And defining it this way breaks every "for .. in" loop, whose code now
must be aware of the hasOwnProperty in -every- object.


I repeat: Show a _specific_ case where that would break and someone will
probably be able point out how to work around it. The very approach of a
general library that handles every possible situation regarding browser
scripting is inevitably a futile one. Recent discussions clearly have
pointed this out, and I strongly suggest you waste no more time on this.

Via my libraries I extend native objects in different ways to ease
programming. Anyone using my libraries is probably aware of the
drawbacks regarding iteration of those objects and objects based
on those.
PointedEars
Nov 24 '05 #8

P: n/a
Howard Jess wrote:

[...]

Fair enough. I have a code library that corrects some browsers's Javascript
misbehavior, and implements missing features. E.g.

var sel = document.createElement('select');
var opt = document.createElement('option');
sel.add(opt,null);
I thought the most widely supported method here was:

var sel = document.createElement('select');
sel.options[sel.options.length] = new Option(...);
Maybe that's what you do in your library...


This doesn't work as is on Internet Explorer (which expects either a
single argument, or an index rather than an object reference for the second
argument); the library (with some help) makes it work.

Similarly,

var obj = {thing:1, otherThing:'abc'};
if (obj.hasOwnProperty('lastThing')) ...

doesn't work in Safari 1.2: that browser doesn't implement hasOwnProperty,
among others.

It's simple enough to implement it and the rest; e.g.:

Object.prototype.hasOwnProperty = function(propName) {
...
}

But in a library, I have no control over user code. And defining it
this way breaks every "for .. in" loop, whose code now must be aware
of the hasOwnProperty in -every- object. *THAT'S* why I'd like to be
able to define a new "DontEnum" property. And yes, I understand it's
not possible in standard JavaScript, and yes, I've begun looking
through the sources; I was hoping someone who frequents this group may
have some insight that might save me some time.
I guess that's a gotcha of JavaScript for..in loops. They've been
discussed here before in relation to sparse arrays, where for..in was
used rather than for..i<array.length and methods had been added to the
Array object or its prototype (e.g. for browsers that don't support
push, splice, etc.).

The answer there was to use a custom object designed for the purpose
(and maybe keeps it's own 'length' property too). Clearly that isn't
what you want.

Thanks for any help or suggestions.


Sorry, none of either...

If it makes you feel any better, it ticks me off that Apple requires the
purchase of an entire OS to get the latest version of their browser,
particularly when it is based on open source. I suppose suggesting
Firefox is of no use? ;-)
--
Rob
Nov 24 '05 #9

P: n/a
VK

RobG wrote:
I suppose suggesting Firefox is of no use? ;-)


Or if the Aqua-style is too precious to you ;-) you may consider Gecko
Camino:
<http://www.caminobrowser.org/>

Safary 1.x - 2.0 is a complete junk as browser. So is the Konqueror
used as the base for it.

Konqueror lesser than 2.2 simply crashes on each site with JavaScript
so you have no chance to make any features check on the first place.

Konqueror 2.2 works 50/50 with JavaScript but there is no common
algorithm to guess where, so there is no use to bother with it.

How this failed programming exercise appeared in both GUI packages (OS
X / KDE) is a great mistery of the new millenium. Definitely some
corporate hash-hash under the carpet we are not aware of.

Any way, Safari 1.x and Konqueror 1.x are not supportable by any
JavaScript checks for the above spelled reasons. Any if-else if -else
's would be a pure waste of time. Just pretend they never existed and
move forward.

Nov 24 '05 #10

P: n/a
hj
RobG wrote:
Howard Jess wrote:

var sel = document.createElement('select');
var opt = document.createElement('option');
sel.add(opt,null);


I thought the most widely supported method here was:

var sel = document.createElement('select');
sel.options[sel.options.length] = new Option(...);
Maybe that's what you do in your library...


Not quite; that was a very simple example. Given:

function moveOption(fromSel,toSel,fromIndex,toIndex) {
var opt = fromSel.options[fromIndex];
if (opt != null) // yes, this is an explicit test
toSel.add(opt,toIndex);
}

According to the W3C spec, there's no reason this should
not work; but you may find it problematic in some browsers.
The library makes it work as expected.
[Caveat: I'm posting from home; this is from memory and untested.]
hj

Nov 24 '05 #11

P: n/a
hj
hj wrote:
Not quite; that was a very simple example. Given:

function moveOption(fromSel,toSel,fromIndex,toIndex) {
var opt = fromSel.options[fromIndex];
if (opt != null) // yes, this is an explicit test
toSel.add(opt,toIndex);
}


Um ... as I was saying ...
function moveOption(fromSel,toSel,fromIndex,toIndex) {
var opt = fromSel.options[fromIndex];
if (opt != null) // yes, this is an explicit test
toSel.add(opt,toSel.options[toIndex]);
}

hj

Nov 24 '05 #12

P: n/a
VK wrote:
RobG wrote:
I suppose suggesting Firefox is of no use? ;-)

Or if the Aqua-style is too precious to you ;-) you may consider Gecko
Camino:
<http://www.caminobrowser.org/>


I've tried Camino, but it's only at version 0.8.4 so while OK for home
use can't really be recommended to a corporate client.

Ooops!! Just checked Mozilla.org, Camino has now hit 1.0b1 - seems they
even got tabs to left-justify!!


Safary 1.x - 2.0 is a complete junk as browser. So is the Konqueror
used as the base for it.


Dunno, I find Safari fine for general web surfing. I like many of the
features, though its support for JavaScript and DOM is disappointing -
but I haven't tried the latest version yet. I'm trying to get OS X 10.4
on eBay but keep getting sniped!
[...]
--
Rob
Nov 24 '05 #13

P: n/a
RobG wrote:
I've tried Camino, but it's only at version 0.8.4 so while OK for home
use can't really be recommended to a corporate client.


I have seen too many good 0.x versions of software to find this argument
justified.
PointedEars
Nov 25 '05 #14

P: n/a
Thomas 'PointedEars' Lahn wrote:
RobG wrote:

I've tried Camino, but it's only at version 0.8.4 so while OK for home
use can't really be recommended to a corporate client.

I have seen too many good 0.x versions of software to find this argument
justified.


I have deal with too many officious system adminstrators not to consider
it. ;-)

Anyhow, it seems 1.0 is (nearly) here.
--
Rob
Nov 25 '05 #15

P: n/a
VK

RobG wrote:
Dunno, I find Safari fine for general web surfing.


I did not say "It's a bad HTML 4.0 renderer". I said "It's a bad
browser". ;-)

Year 2005 these are very different kinds.

Nov 25 '05 #16

P: n/a
hj
hj wrote:
hj wrote:
Not quite; that was a very simple example. Given:

function moveOption(fromSel,toSel,fromIndex,toIndex) {
var opt = fromSel.options[fromIndex];
if (opt != null) // yes, this is an explicit test
toSel.add(opt,toIndex);
}


Um ... as I was saying ...
function moveOption(fromSel,toSel,fromIndex,toIndex) {
var opt = fromSel.options[fromIndex];
if (opt != null) // yes, this is an explicit test
toSel.add(opt,toSel.options[toIndex]);
}


or even (accounting for both per-spec and IE-specific behavior):

function moveOption(fromSel,toSel,fromIndex,toIndex) {
var opt = fromSel.options[fromIndex];
if (opt != null) // yes, this is an explicit test
try {toSel.add(opt,toSel.options[toIndex])} catch(err) {
toSel.add(opt,toIndex);
}
}

hj

Nov 26 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.