Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > Adding new methods to existing classes

Reply
Thread Tools

Adding new methods to existing classes

 
 
Phat G5 (G3)
Guest
Posts: n/a
 
      08-27-2007
I was toying around with adding a new method to the Array class. It works
fine in FF but not in Safari. I have no idea in IE. I have not gotten that
far yet.

Array.prototype.find = function(item) { for(var i in this )
if( item == this(i) )
return( true )
return( false );
};

Any suggestions?

Thanks, S

 
Reply With Quote
 
 
 
 
RobG
Guest
Posts: n/a
 
      08-27-2007
On Aug 27, 1:55 pm, "Phat G5 (G3)" <(E-Mail Removed)> wrote:
> I was toying around with adding a new method to the Array class. It works
> fine in FF but not in Safari. I have no idea in IE. I have not gotten that
> far yet.
>
> Array.prototype.find = function(item) { for(var i in this )
> if( item == this(i)


Don't forget to manually wrap your code at about 70 characters to
allow for auto-wrapping.

IE often confuses () with [], maybe you have discovered Firefox trying
to make allowances for that (or not... just a guess).

Try:

if( item == this[i] )


--
Rob

 
Reply With Quote
 
 
 
 
Phat G5 (G3)
Guest
Posts: n/a
 
      08-27-2007
in article (E-Mail Removed). com, RobG at
(E-Mail Removed) wrote on 8/27/07 1:52 AM:

> On Aug 27, 1:55 pm, "Phat G5 (G3)" <(E-Mail Removed)> wrote:
>> I was toying around with adding a new method to the Array class. It works
>> fine in FF but not in Safari. I have no idea in IE. I have not gotten that
>> far yet.
>>
>> Array.prototype.find = function(item) { for(var i in this )
>> if( item == this(i)

>
> Don't forget to manually wrap your code at about 70 characters to
> allow for auto-wrapping.
>
> IE often confuses () with [], maybe you have discovered Firefox trying
> to make allowances for that (or not... just a guess).
>
> Try:
>
> if( item == this[i] )
>
>
> --
> Rob
>

That was a typo I had fixed and forgot to post before sending. Sorry. Here
is a basic idea of what I was doing.

Array.prototype.find = function(item) { for( var i in this )
if( item == this[i] )
return( true )
return( false );
};

var groups = new Array(0);
var dials = x.form.getElementsByTagName("input")
for( var i in dials )
if( dials[i].type == "radio" && !groups.find(dials[i].name) )
groups = groups.concat(new Array(dials[i].name))


I was trying to go thru the radio dials of a form and create an array of
just the radio dial groups/names and then be able to parse the groups one at
a time like theForm.elements[groups[i]][j].checked. Checking the output of
groups yields an empty array. For testing purposes I just took the above
method and did a quick test.

var x = new Array("zz");
alert(x.find("zz")) returns false every time in Safari and IE6+7 but true in
Firefox.


It would appear the prototype registers but it's not recognizing it's own
attributes and never iterates thru them and ultimately hits return false.
Changing from a for..in loop to a regular for loop makes no difference. Any
other suggestions?

Thanks

-S

 
Reply With Quote
 
David Golightly
Guest
Posts: n/a
 
      08-28-2007
On Aug 27, 6:45 am, "Phat G5 (G3)" <(E-Mail Removed)> wrote:
> var x = new Array("zz");
> alert(x.find("zz")) returns false every time in Safari and IE6+7 but true in
> Firefox.
>
> It would appear the prototype registers but it's not recognizing it's own
> attributes and never iterates thru them and ultimately hits return false.
> Changing from a for..in loop to a regular for loop makes no difference. Any
> other suggestions?


Well, yes:

1. Use [], not the Array constructor.
2. Never, ever use the for .. in syntax to iterate through an Array,
*especially* if you're extending Array.prototype. Use a conventional
for (var i=0, len=this.length; i<len; i++) loop instead.
3. Don't use parentheses with the "return" keyword.
4. Always end lines in semicolons.
5. If you're having trouble with loops and/or if statements, wrap
their blocks in curly braces {}.

Run your code through JSLint (http://www.jslint.com/lint.html) for
some enlightening suggestions.

Thus, your code becomes:

Array.prototype.find = function (item) {
for (var i=0; i<this.length; i++) {
if (this[i] == item) {
return true;
}
}
return false;
};

such that the test ['a', 'b', 'c'].find('b') === true in IE.

But a better technique would be to implement JS 1.6's

if (typeof Array.prototype.indexOf != 'function') {
Array.prototype.indexOf = function (item) {
// .. implementation here
// see http://developer.mozilla.org/en/docs...:Array:indexOf
}
}

as it's already there on most every browser but IE.

-David

 
Reply With Quote
 
Phat G5 (G3)
Guest
Posts: n/a
 
      08-28-2007
in article (E-Mail Removed). com, David
Golightly at (E-Mail Removed) wrote on 8/27/07 6:23 PM:

> On Aug 27, 6:45 am, "Phat G5 (G3)" <(E-Mail Removed)> wrote:
>> var x = new Array("zz");
>> alert(x.find("zz")) returns false every time in Safari and IE6+7 but true in
>> Firefox.
>>
>> It would appear the prototype registers but it's not recognizing it's own
>> attributes and never iterates thru them and ultimately hits return false.
>> Changing from a for..in loop to a regular for loop makes no difference. Any
>> other suggestions?

>
> Well, yes:
>
> 1. Use [], not the Array constructor.
> 2. Never, ever use the for .. in syntax to iterate through an Array,
> *especially* if you're extending Array.prototype. Use a conventional
> for (var i=0, len=this.length; i<len; i++) loop instead.
> 3. Don't use parentheses with the "return" keyword.
> 4. Always end lines in semicolons.
> 5. If you're having trouble with loops and/or if statements, wrap
> their blocks in curly braces {}.
>
> Run your code through JSLint (http://www.jslint.com/lint.html) for
> some enlightening suggestions.
>
> Thus, your code becomes:
>
> Array.prototype.find = function (item) {
> for (var i=0; i<this.length; i++) {
> if (this[i] == item) {
> return true;
> }
> }
> return false;
> };
>
> such that the test ['a', 'b', 'c'].find('b') === true in IE.
>
> But a better technique would be to implement JS 1.6's
>
> if (typeof Array.prototype.indexOf != 'function') {
> Array.prototype.indexOf = function (item) {
> // .. implementation here
> // see
> http://developer.mozilla.org/en/docs...ce:Global_Obje
> cts:Array:indexOf
> }
> }
>
> as it's already there on most every browser but IE.
>
> -David
>

David,

Thank you for your suggestions... I was unsure what you meant by one of the
things. Item 1 you said :
> 1. Use [], not the Array constructor.

Was that in relation to the question I had about the following?

> var groups = new Array(0);
> var dials = x.form.getElementsByTagName("input")
> for( var i in dials )
> if( dials[i].type == "radio" && !groups.find(dials[i].name) )
> groups = groups.concat(new Array(dials[i].name))
>
>
> I was trying to go thru the radio dials of a form and create an array of
> just the radio dial groups/names and then be able to parse the groups one at
> a time like theForm.elements[groups[i]][j].checked.



Not sure. Could you please elaborate?


Thanks again,

-S

 
Reply With Quote
 
Phat G5 (G3)
Guest
Posts: n/a
 
      08-28-2007
in article (E-Mail Removed). com, David
Golightly at (E-Mail Removed) wrote on 8/27/07 6:23 PM:

> On Aug 27, 6:45 am, "Phat G5 (G3)" <(E-Mail Removed)> wrote:
>> var x = new Array("zz");
>> alert(x.find("zz")) returns false every time in Safari and IE6+7 but true in
>> Firefox.
>>
>> It would appear the prototype registers but it's not recognizing it's own
>> attributes and never iterates thru them and ultimately hits return false.
>> Changing from a for..in loop to a regular for loop makes no difference. Any
>> other suggestions?

>
> Well, yes:
>
> 1. Use [], not the Array constructor.
> 2. Never, ever use the for .. in syntax to iterate through an Array,
> *especially* if you're extending Array.prototype. Use a conventional
> for (var i=0, len=this.length; i<len; i++) loop instead.
> 3. Don't use parentheses with the "return" keyword.
> 4. Always end lines in semicolons.
> 5. If you're having trouble with loops and/or if statements, wrap
> their blocks in curly braces {}.
>
> Run your code through JSLint (http://www.jslint.com/lint.html) for
> some enlightening suggestions.
>
> Thus, your code becomes:
>
> Array.prototype.find = function (item) {
> for (var i=0; i<this.length; i++) {
> if (this[i] == item) {
> return true;
> }
> }
> return false;
> };
>
> such that the test ['a', 'b', 'c'].find('b') === true in IE.
>
> But a better technique would be to implement JS 1.6's
>
> if (typeof Array.prototype.indexOf != 'function') {
> Array.prototype.indexOf = function (item) {
> // .. implementation here
> // see
> http://developer.mozilla.org/en/docs...ce:Global_Obje
> cts:Array:indexOf
> }
> }
>
> as it's already there on most every browser but IE.
>
> -David
>

David,

I think I figured out what you meant about option 1. Is this the suggested
change?

var groups = [];
var dials = x.form.getElementsByTagName("input")
for( var i =0; i<dials.length; i++ )
if( dials[i].type == "radio" && !groups.find(dials[i].name) )
groups = groups.concat([dials[i].name]);

It does work... But, is there a better/more efficient and less code
dependent way of doing this?


Thanks

-S




 
Reply With Quote
 
Thomas 'PointedEars' Lahn
Guest
Posts: n/a
 
      08-28-2007
David Golightly wrote:
> On Aug 27, 6:45 am, "Phat G5 (G3)" <(E-Mail Removed)> wrote:
>> var x = new Array("zz");
>> alert(x.find("zz")) returns false every time in Safari and IE6+7 but true in
>> Firefox.
>>
>> It would appear the prototype registers but it's not recognizing it's own
>> attributes and never iterates thru them and ultimately hits return false.
>> Changing from a for..in loop to a regular for loop makes no difference. Any
>> other suggestions?

>
> Well, yes:
>
> 1. Use [], not the Array constructor.


Given that the Array initializer `[...]' is not universally supported
(introduced in JavaScript 1.3, JScript 2.0, ECMAScript 3), but Array() can
be considered to be so (introduced in JavaScript 1.1, JScript 1.0,
ECMAScript 1), that is bad advice.

There is nothing wrong with the Array constructor as long as it is watched
for what the first argument is; if it is a number, it is
implementation-dependent whether the first argument denotes the number of
elements that are initialized with `undefined' in the encapsulated array
data structure, or the value of the first and only initialized element of
that array.

> 2. Never, ever use the for .. in syntax to iterate through an Array,


Depends. When order is not significant, there is nothing wrong in using
for...in, which is supported since the very first implementations.

> *especially* if you're extending Array.prototype.


The reasoning is flawed. Because of the issue with the `in' operator, one
should have very good reasons before augmenting the Array.prototype object.
However, the `in' operator can still be used if used within a wrapper
method for the augmented prototype.

> Use a conventional for (var i=0, len=this.length; i<len; i++) loop instead.


That is correct when order is significant, however it is less efficient when
it is not. Also, if iteration in reverse order is acceptable,

for (var i = this.length; i--

is more efficient than the above.

> 3. Don't use parentheses with the "return" keyword.


There is nothing wrong with doing that. And given that some expressions do
not fit on one line if code style is observed, and that automatic semicolon
insertion exists, this is bad advice.

> 4. Always end lines in semicolons.


That ignores that a line does not need to end a statement, which turns it
into bad advice.

> 5. If you're having trouble with loops and/or if statements, wrap
> their blocks in curly braces {}.


All loop/conditional code blocks that do not fit the loop statement line or
consist of more than one line (code style applied) should be wrapped so.

> Run your code through JSLint (http://www.jslint.com/lint.html) for
> some enlightening suggestions.


For you as well.

> Thus, your code becomes:
>
> Array.prototype.find = function (item) {
> for (var i=0; i<this.length; i++) {


Order is not significant here.

> if (this[i] == item) {
> return true;
> }
> }
> return false;
> };
>
> such that the test ['a', 'b', 'c'].find('b') === true in IE.


That ignores that `==' is a type-converting comparison. Therefore, with
the above code, e.g. [false].find(0) yields true as well, as does
[true].find(1).

Array.prototype.find = function(item)
{
for (var i = this.length; i--
{
if (this[i] === item)
{
return true;
}
}

return false;
};

> But a better technique would be to implement JS 1.6's
> [...]
> as it's already there on most every browser but IE.


It is implemented since JavaScript 1.6 in Gecko-based UAs, and is not
part of any standard. That is hardly "most every browser but IE".


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
 
Reply With Quote
 
David Golightly
Guest
Posts: n/a
 
      08-28-2007
On Aug 28, 1:56 am, Thomas 'PointedEars' Lahn wrote:
> David Golightly wrote:
> > 1. Use [], not the Array constructor.

>
> Given that the Array initializer `[...]' is not universally supported
> (introduced in JavaScript 1.3, JScript 2.0, ECMAScript 3), but Array() can
> be considered to be so (introduced in JavaScript 1.1, JScript 1.0,
> ECMAScript 1), that is bad advice.


As always, I can learn from your dogmatic advice. Though in this case
it's baseless; it's folly to even start to think about supporting
browsers made (and abandoned by their makers) before 1999, unless you
have very specific reasons for doing so. Preferring [] to - new
Array(0) - is recommended by the standardistas I care about, such as
Brendan Eich and Douglas Crockford, so I'll ignore your suggestion
here.

> > 2. Never, ever use the for .. in syntax to iterate through an Array,
> > *especially* if you're extending Array.prototype.

>
> The reasoning is flawed. Because of the issue with the `in' operator, one
> should have very good reasons before augmenting the Array.prototype object.
> However, the `in' operator can still be used if used within a wrapper
> method for the augmented prototype.


The reasoning is hardly flawed. Unless you really know what you're
doing, you don't have much reason to do either thing. So this is a
fine rule of thumb. Care to give an example of what you're talking
about here?

>
> > Use a conventional for (var i=0, len=this.length; i<len; i++) loop instead.

>
> That is correct when order is significant, however it is less efficient when
> it is not. Also, if iteration in reverse order is acceptable,
>
> for (var i = this.length; i--
>
> is more efficient than the above.


Perhaps. Could you explain?

>
> > 3. Don't use parentheses with the "return" keyword.

>
> There is nothing wrong with doing that. And given that some expressions do
> not fit on one line if code style is observed, and that automatic semicolon
> insertion exists, this is bad advice.


Nope again. A paren *might* be advisable to wrap a long expression,
but should not be used automatically with - return - as though it were
a function. See Crockford (ibid.) for justification.

> > 4. Always end lines in semicolons.

>
> That ignores that a line does not need to end a statement, which turns it
> into bad advice.


Nitpicking. Too often semicolons are left off where they're later
inserted by the compiler, which leads to bugs.

> > Run your code through JSLint (http://www.jslint.com/lint.html) for
> > some enlightening suggestions.

>
> For you as well.


Hm, I don't see that my code produces any errors in JSLint. Give an
example. Also, JSLint exists to *enlighten*, not to enforce.

> > But a better technique would be to implement JS 1.6's
> > [...]
> > as it's already there on most every browser but IE.

>
> It is implemented since JavaScript 1.6 in Gecko-based UAs, and is not
> part of any standard. That is hardly "most every browser but IE".


Not quite. Webkit-based browsers (Safari/Konquereror) implement this
as well. And it's better to start with something that's at least
*partially* compatible with *some* browsers than invent your own
solution that's not compatible with *any* browser.

-David

 
Reply With Quote
 
Thomas 'PointedEars' Lahn
Guest
Posts: n/a
 
      08-28-2007
David Golightly wrote:
> On Aug 28, 1:56 am, Thomas 'PointedEars' Lahn wrote:
>> David Golightly wrote:
>>> 1. Use [], not the Array constructor.

>> Given that the Array initializer `[...]' is not universally supported
>> (introduced in JavaScript 1.3, JScript 2.0, ECMAScript 3), but Array() can
>> be considered to be so (introduced in JavaScript 1.1, JScript 1.0,
>> ECMAScript 1), that is bad advice.

>
> As always, I can learn from your dogmatic advice.


It is not dogmatic, it merely points out the flaws in your "argumentation".

BTW: It was you you who started giving dogmatic advice by recommending that
the Array constructor should not be used, without providing a reason for
that recommendation.

> Though in this case it's baseless; it's folly to even start to think about
> supporting browsers made (and abandoned by their makers) before 1999, unless
> you have very specific reasons for doing so.


The very specific reason is backwards compatibility.

> Preferring [] to - new Array(0) -


As I said, those two are *not* semantically identical.

> is recommended by the standardistas I care about, such as Brendan Eich and
> Douglas Crockford, so I'll ignore your suggestion here.


Logical fallacy: ipse dixit. <http://en.wikipedia.org/wiki/Appeal_to_authority>

See below.

>>> 2. Never, ever use the for .. in syntax to iterate through an Array,
>>> *especially* if you're extending Array.prototype.

>> The reasoning is flawed. Because of the issue with the `in' operator, one
>> should have very good reasons before augmenting the Array.prototype object.
>> However, the `in' operator can still be used if used within a wrapper
>> method for the augmented prototype.

>
> The reasoning is hardly flawed.


Yes, it is. It is implying that iterating through an array always has to
follow an order; it is also saying that for...in should not be used on Array
objects (no matter the reason), and it is implying that a valid reason for
not using for...in on Array objects is that their prototype object may be
augmented.

> Unless you really know what you're doing, you don't have much reason to do
> either thing.


If you do not really know what you are doing, you should not do anything
because the results would be ultimately fatal otherwise.

> So this is a fine rule of thumb. Care to give an example of what you're talking
> about here?


/**
* @see http://PointedEars.de/scripts/types.js
*/
function isMethodType(s)
{
return /\b(function|object)\b/i.test(s);
}

Array.prototype.forEach = function(callback)
{
if (isMethodType(typeof callback) && callback)
{
var h = isMethodType(typeof this.hasOwnProperty)
&& this.hasOwnProperty;
for (var i in this)
{
if ((h && this.hasOwnProperty(i))

// or implement a search for previously
// registered property names here
|| (!h && i != "forEach"))
{
callback(i, this);
}
}
}
};

>>> Use a conventional for (var i=0, len=this.length; i<len; i++) loop instead.

>> That is correct when order is significant, however it is less efficient when
>> it is not. Also, if iteration in reverse order is acceptable,
>>
>> for (var i = this.length; i--
>>
>> is more efficient than the above.

>
> Perhaps. Could you explain?


0 evaluates to `false', anything else evaluates to `true'.

>>> 3. Don't use parentheses with the "return" keyword.

>> There is nothing wrong with doing that. And given that some expressions do
>> not fit on one line if code style is observed, and that automatic semicolon
>> insertion exists, this is bad advice.

>
> Nope again. A paren *might* be advisable to wrap a long expression,
> but should not be used automatically with - return - as though it were
> a function.


Whitespace between keyword and value suffices for the keyword not to be
misinterpreted by the human reader as a function/method. It is merely a
matter of code style.

> See Crockford (ibid.) for justification.


Same fallacy here.

>>> 4. Always end lines in semicolons.

>> That ignores that a line does not need to end a statement, which turns it
>> into bad advice.

>
> Nitpicking. Too often semicolons are left off where they're later
> inserted by the compiler, which leads to bugs.


I did not debate that.

>>> Run your code through JSLint (http://www.jslint.com/lint.html) for
>>> some enlightening suggestions.

>> For you as well.

>
> Hm, I don't see that my code produces any errors in JSLint. Give an
> example. Also, JSLint exists to *enlighten*, not to enforce.


Enlightenment is man's leaving his self-caused immaturity. Immaturity is
the incapacity to use one's intelligence without the guidance of another.
-- Immanuel Kant, "What is Enlightenment?" (1784)

>>> But a better technique would be to implement JS 1.6's
>>> [...]
>>> as it's already there on most every browser but IE.

>> It is implemented since JavaScript 1.6 in Gecko-based UAs, and is not
>> part of any standard. That is hardly "most every browser but IE".

>
> Not quite. Webkit-based browsers (Safari/Konquereror) implement this
> as well.


At least
http://developer.kde.org/documentati...pp-source.html
contains nothing of the kind.

> And it's better to start with something that's at least
> *partially* compatible with *some* browsers than invent your own
> solution that's not compatible with *any* browser.


Flawed reasoning again. Any own (user-defined) solution would have to
be compatible with any browser, or it does not deserve its designation.


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$(E-Mail Removed)>
 
Reply With Quote
 
Thomas 'PointedEars' Lahn
Guest
Posts: n/a
 
      08-28-2007
Thomas 'PointedEars' Lahn wrote:
> David Golightly wrote:
>> On Aug 28, 1:56 am, Thomas 'PointedEars' Lahn wrote:
>>> David Golightly wrote:
>>>> But a better technique would be to implement JS 1.6's
>>>> [...]
>>>> as it's already there on most every browser but IE.
>>> It is implemented since JavaScript 1.6 in Gecko-based UAs, and is not
>>> part of any standard. That is hardly "most every browser but IE".

>> Not quite. Webkit-based browsers (Safari/Konquereror) implement this
>> as well.

>
> At least
> http://developer.kde.org/documentati...pp-source.html
> contains nothing of the kind.


And neither does

http://developer.kde.org/documentati...pp-source.html

which would apply to Konqueror 3.5.x.

It should also be noted that Konqueror is *not* based on Apple WebKit;
it uses KHTML. Konqueror's ECMAScript implementation is KJS.

Apple Safari uses WebKit, which contains WebCore (based on KHTML) and
JavaScriptCore (based on KJS). However,

http://trac.webkit.org/projects/webk...ray_object.cpp

also does not contain anything that would indicate Safari would support
Array.prototype.indexOf(). I will test that on our Mac later, but I don't
expect to be surprised here.


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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Adding an interface to existing classes Spencer Pearson Python 14 01-05-2012 07:56 AM
Is there a way to find the class methods of a class, just like'methods' finds the instance methods? Kenneth McDonald Ruby 5 09-26-2008 03:09 PM
methods, methods override classes and scope Ramza Brown Ruby 1 04-18-2006 07:38 AM
Adding new methods to new-style classes dynamically Max Derkachev Python 4 05-05-2005 04:38 PM
How to access inner classes variables & methods from outer classes lonelyplanet999 Java 1 11-13-2003 01:54 PM



Advertisments