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

Property vs. Hash Key

P: n/a
Hi,

I am familiar with the ruby language.
To use my ruby knowledge when writing in JavaScript, I use the
following library.

http://www.advogato.org/proj/Ruby.js/

If I include the file in my html, I can use ruby style methods in
JavaScript.
Basically, it adds properties to the basic prototypes like Object and
Array.
And I am pleased with that.

But there's one glitch.
If I create a hash, the properties added above are already registered
as keys.
So if I loop through keys, the custom properties (not the keys I want
for the hash) are called.
What's the best way to address this problem?
One solution might be using a prefix in the hash keys.
Not an elegant way, though.

Any good idea?

Thanks.

Sam

Oct 16 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a
VK

Sam Kong wrote:
If I include the file in my html, I can use ruby style methods in
JavaScript.
Basically, it adds properties to the basic prototypes like Object and
Array.
And I am pleased with that.
IMHO you should be upset for the first one.
Augmenting Object.prototype itself is a very rude behavior because I
breaks expectations for all custom objects (custom properties are
enumerable unlike the native ones).
IMHO
If I create a hash, the properties added above are already registered
as keys.
So if I loop through keys, the custom properties (not the keys I want
for the hash) are called.
What's the best way to address this problem?
One solution might be using a prefix in the hash keys.
Not an elegant way, though.
Other way could be to study each property to sort out the inherited
properties from the own ones.

<script type="text/javascript">
Object.prototype.inheritedMethod = function(){
window.alert('inherited method');
}

function MyObject() {
this.ownMethod = function(){
window.alert('own method');
}
}

var obj = new MyObject;

alert( obj.propertyIsEnumerable('toString') ); // false
alert( obj.propertyIsEnumerable('inheritedMethod') ); // false
alert( obj.propertyIsEnumerable('ownMethod') ); // true

alert( ('toString' in obj) ); // true
alert( obj.hasOwnProperty('toString') ); //false

alert( ('inheritedMethod' in obj) ); // true
alert( obj.hasOwnProperty('inheritedMethod') ); //false

alert( ('ownMethod' in obj) ); // true
alert( obj.hasOwnProperty('ownMethod') ); //true
</script>

IMHO better yet would be to contact the library author and to suggest
him to use a regular OOP paradigm (or find a library using said
paradigm). Thus Object would be left alone, say rObject created on base
of it with extra properties and all library objects based then on
rObject.

Oct 16 '06 #2

P: n/a
Sam Kong wrote:
Hi,

I am familiar with the ruby language.
To use my ruby knowledge when writing in JavaScript, I use the
following library.

http://www.advogato.org/proj/Ruby.js/

If I include the file in my html, I can use ruby style methods in
JavaScript.
Basically, it adds properties to the basic prototypes like Object and
Array.
And I am pleased with that.
Many others aren't, it is one of the major ciriticisms of libraries
like Ruby and Prototype.

But there's one glitch.
If I create a hash, the properties added above are already registered
as keys.
So if I loop through keys, the custom properties (not the keys I want
for the hash) are called.
Don't think of hashes or keys or whatever, think of them all as just
named properties. Javascript Objects are quite simple, they are
essentially just bundles of named properties. The only non-enumerable
properties are the built-in ones, you can't add non-enumerable
properties using javascript.

What's the best way to address this problem?
Don't use Ruby.js, or any other library that extends built-in objects
like Object and Array. :-)

One solution might be using a prefix in the hash keys.
Not an elegant way, though.
Not elegant at all, and possibly impractical as it infers that you have
complete control of property names, which you may not have.

You can test the property using hasOwnProperty, it will return true
only for properties of the object itself, not any in the prototype
chain:

// Add custom property to all objects
Object.prototype.objTestProp = 'fooObj';

// Constructor
function Fred(){}

// Add property to prototype
Fred.prototype.fredTestProp = 'fooFred';

// Create instance of Fred and add another property
var x = new Fred();
x.xTestProp = 'fooX';

// Which properties are on x and which on prototype chain?
var msg = [];
for (var prop in x){
if (x.hasOwnProperty(prop)){
msg.push(prop + ' is a property of x');
} else {
msg.push(prop + ' is from prototype chain');
}
}
alert(msg.join('\n'));
But that is a fairly limited strategy.
--
Rob

Oct 16 '06 #3

P: n/a
Hi Rob,

RobG wrote:
Don't use Ruby.js, or any other library that extends built-in objects
like Object and Array. :-)
Well, that's overkill! ;-)

You can test the property using hasOwnProperty, it will return true
only for properties of the object itself, not any in the prototype
chain:
But that is a fairly limited strategy.
I like this solution.
Why do you think it's a fairly limited strategy?
It may be a reliable solution, Isn't it?
When I make a hash, I add keys to the object.
And they are all true to obj.hasOwnProperty.
Am I wrong?

Thanks.

Sam

Oct 16 '06 #4

P: n/a
VK

RobG wrote:
Basically, it adds properties to the basic prototypes like Object and
Array.
And I am pleased with that.
Many others aren't, it is one of the major ciriticisms of libraries
like Ruby and Prototype.
Sustand :-)

In addition to my previous post I have forgotten to mention that
propertyIsEnumerable doesn't study the prototype chain - unlike ('prop'
in obj) does - so it's internally:
if ( obj.hasOwnProperty('prop') && obj.propertyIsEnumerable('prop') )

This way in-loop check could be as simple as:

for (prop in obj) {
if (obj.propertyIsEnumerable(prop) {
// your stuff to work with
}
}

Oct 16 '06 #5

P: n/a
VK
This way in-loop check could be as simple as:
>
for (prop in obj) {
if (obj.propertyIsEnumerable(prop) {
// your stuff to work with
}
}
Oops... sign it off for the night time...
I've forgotten that in this case there is no need to study the chain as
the property is already provided from for-in loop so you'll get false
true's. Or you'll not? Better check through...

It seems that

for (prop in obj) {
if (obj.hasOwnProperty(prop) && obj.propertyIsEnumerable(prop) {
// your stuff to work with
}
}

is the most reliable - but it leads to a productivity impact on large
property sets, what kind of impact and if negleagible - better check
through.

Oct 16 '06 #6

P: n/a
Sam Kong wrote:
Hi,

I am familiar with the ruby language.
To use my ruby knowledge when writing in JavaScript, I use the
following library.

http://www.advogato.org/proj/Ruby.js/

If I include the file in my html, I can use ruby style methods in
JavaScript.
Basically, it adds properties to the basic prototypes like Object and
Array.
And I am pleased with that.

But there's one glitch.
If I create a hash, the properties added above are already registered
as keys.
So if I loop through keys, the custom properties (not the keys I want
for the hash) are called.
What's the best way to address this problem?
One solution might be using a prefix in the hash keys.
Not an elegant way, though.

Any good idea?
JavaScript has a prototypal inheritance scheme which allows an object to inherit
properties from another object. These can be chained, ultimately terminating at
Object.prototype.

Unfortunately, the for..in statement dredges through all of the inherited
properties, and as you discovered, that is undesirable.

So you need to filter out those extra members each time you loop. It is annoying
but necessary. See http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
Oct 16 '06 #7

P: n/a
Sam Kong wrote:
So if I loop through keys, the custom properties (not the keys I want
for the hash) are called.
What's the best way to address this problem?
Personally, when I'm not concerned about speed, I take a cue from Ruby
and create a nice iterator on Objects:

Object.prototype.each = function( inCallback, inScope ){
if ( !inScope ) inScope = this;
for ( var theKey in this ){
if ( this.hasOwnProperty( theKey ){
inCallback.call( inScope, theKey, this[ theKey ] );
}
}
}

var geeky = { foo:true, bar:true, jimmy:false }

geeky.each( function( name, isGeekyFlag ) {
if ( isGeekyFlag ){
alert( name + " is a geeky variable name" );
}
} );

Oct 16 '06 #8

P: n/a
Hi Douglas,

Douglas Crockford wrote:
See http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
That's a very useful blog.
Thanks.

Sam

Oct 16 '06 #9

P: n/a
Hi Phrogz,

Phrogz wrote:
Personally, when I'm not concerned about speed, I take a cue from Ruby
and create a nice iterator on Objects:
Yes. ruby.js provides such nice methods. Even mix-in.
I had used JavaScript even before I used Ruby.
And I realized how good JavaScript was only after I understood that
JavaScript was flexible enough to mimic Ruby.

Thanks.
Sam

Oct 16 '06 #10

P: n/a

Sam Kong wrote:
Hi Douglas,

Douglas Crockford wrote:
See http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
I checked out the ruby.js library and found out that it already used
hasOwnProperty internally to implement ruby style hash.

Hash.prototype.has = Hash.prototype.includes = Hash.prototype.hasKey =
function(key) {
return(hasOwnProperty("item_" + key.hash()))
}

It also uses a prefix to distinguish keys from other properties.
Sam

Oct 16 '06 #11

P: n/a

Sam Kong wrote:
Hi Rob,

RobG wrote:
[...]
You can test the property using hasOwnProperty, it will return true
only for properties of the object itself, not any in the prototype
chain:
But that is a fairly limited strategy.

I like this solution.
Why do you think it's a fairly limited strategy?
As Richard's link indicated, it has limited support in some browsers
and all functions that employ for..in need to do the test, including
those from other libraries you might be using (maybe authors will start
publishing "extended-Object safe" versions).

In addition, there may be properties in the prototype chain that you
*do* want to iterate over, and there must be a performance hit in doing
the extra if test (which may be insignificant in most cases but it is
still annoying).

It may be a reliable solution, Isn't it?
Other than the above, yes.
--
Rob

Oct 16 '06 #12

P: n/a
Sam Kong wrote:
But there's one glitch.
If I create a hash, the properties added above are already registered
as keys.
So if I loop through keys, the custom properties (not the keys I want
for the hash) are called.
What's the best way to address this problem?
One solution might be using a prefix in the hash keys.
This might be helpful:

http://dean.edwards.name/weblog/2006/07/erlaubt/

Oct 17 '06 #13

P: n/a
Hi runsun,

runsun pan wrote:
This might be helpful:

http://dean.edwards.name/weblog/2006/07/erlaubt/
Yes. That's helpful.
Actually, the reason I use ruby.js is that I want to use the great ruby
methods.
One of them is each.

If you use ruby.js, you can code like the following.

[1, 2, 3].each(function(i) { foo(i); });

Very similar the forEach method.

I wonder why Mozilla made external iterator like Array.forEach instead
of providing the internal iterator to all iteratable objects.

Thanks.
Sam

Oct 17 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.