Array.prototype and "this"

D

Denis McMahon

I have functions that return first, last or list of array indexes where
the array value is x. An example:

<script type="text/javascript">
function arrayFirstIndexOf(x, a) { // find first x in array a
for (var i=0, l=a.length; i < l; ++i) if (a === x) return i;
return false;
}
</script">

I thought I'd try and add these as array methods using Array.prototype:

<script type="text/javascript">
Array.prototype.firstIndexOf = function(x) { // find first x in array
for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
return false;
};
</script>

The plan is that then, any array will have an Array.firstIndexOf(x)
method.

However, and I suspect this is a closure issue, I start getting
unexpected "undefined" results when I add the array prototype definition,
even when not actually calling it.

So, it's not only not doing what I want, but it's also doing something
else that breaks previously working code. :(

Then I tried this:

<script type="text/javascript">
function arrayFirstIndexOf(x) { // find first x in array
for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
return false;
}
Array.prototype.firstIndexOf = arrayFirstIndexOf;
</script>

and that didn't work either.

So I guess I'm missing something pretty fundamental either (a) relating
to "this" when using prototype, or (b) relating to closures, or (c) both.

But I can't for the life of me see what I'm missing. :(

Any non cryptic hints and / or pointers would be appreciated.

Rgds

Denis McMahon
 
J

J.R.

I have functions that return first, last or list of array indexes where
the array value is x. An example:

<script type="text/javascript">
function arrayFirstIndexOf(x, a) { // find first x in array a
for (var i=0, l=a.length; i< l; ++i) if (a === x) return i;
return false;
}
</script">

I thought I'd try and add these as array methods using Array.prototype:

<script type="text/javascript">
Array.prototype.firstIndexOf = function(x) { // find first x in array
for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
return false;
};
</script>

The plan is that then, any array will have an Array.firstIndexOf(x)
method.

However, and I suspect this is a closure issue, I start getting
unexpected "undefined" results when I add the array prototype definition,
even when not actually calling it.

So, it's not only not doing what I want, but it's also doing something
else that breaks previously working code. :(

Then I tried this:

<script type="text/javascript">
function arrayFirstIndexOf(x) { // find first x in array
for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
return false;
}
Array.prototype.firstIndexOf = arrayFirstIndexOf;
</script>

and that didn't work either.

So I guess I'm missing something pretty fundamental either (a) relating
to "this" when using prototype, or (b) relating to closures, or (c) both.

But I can't for the life of me see what I'm missing. :(

Any non cryptic hints and / or pointers would be appreciated.



ECMA-262 5th ed., 15.4.4.14, defines the Array.prototype.indexOf()
method. And as recent versions of the major browsers implement the new
Array methods, I think you should always test for the existence of these
methods before adding them to the Array.Prototype object. E.g.:

See
<https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf>

if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */) {
"use strict";

if (this === void 0 || this === null) {
throw new TypeError();
}

var t = Object(this), n = 0,
len = t.length >>> 0;
if (len === 0) { return -1; }

if (arguments.length > 0) {
n = Number(arguments[1]);
if (n !== n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}

if (n >= len) { return -1; }

var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);

for (; k < len; k++) {
if (k in t && t[k] === searchElement) { return k; }
}
return -1;
};
}

Cheers,
Joao Rodrigues (J.R.)
 
R

Richard Cornford

I have functions that return first, last or list of array indexes
where the array value is x. An example:

<script type="text/javascript">
function arrayFirstIndexOf(x, a) { // find first x in array a
for (var i=0, l=a.length; i < l; ++i) if (a === x) return i;
return false;


This - false - seems like a dubious return value in the event that the
value is not found in the array. The usual fail status for an index
reporting function (in contexts where indexes are never negative)
would be -1, but NaN would also be an option.
}
</script">

I thought I'd try and add these as array methods using
Array.prototype:

<script type="text/javascript">
Array.prototype.firstIndexOf = function(x) {
// find first x in array
for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
return false;
};
</script>

The plan is that then, any array will have an Array.firstIndexOf(x)
method.

However, and I suspect this is a closure issue,


It isn't.
I start getting unexpected "undefined" results

What exactly are ""undefined" results"? Are you talking about specific
error messages, or some unexpected/undesirable behaviour in your code?
when I add the array prototype definition,
even when not actually calling it.

A bold assertion, but where are the details and where is the evidence?
So, it's not only not doing what I want, but it's also doing
something else that breaks previously working code. :(

You say that but the code you have posted above looks fine.
Then I tried this:

<script type="text/javascript">
function arrayFirstIndexOf(x) { // find first x in array
for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
return false;
}
Array.prototype.firstIndexOf = arrayFirstIndexOf;
</script>

and that didn't work either.


But again it should be fine.
So I guess I'm missing something pretty fundamental either
(a) relating to "this" when using prototype, or (b) relating
to closures, or (c) both.

No, it looks to me more like you are missing something pretty
fundamental about the actual code you are using. But as you have not
provided any example of any issue demonstrating code you won't make
much progress from here.
But I can't for the life of me see what I'm missing. :(

And nobody else can see what you actually did.
Any non cryptic hints and / or pointers would be appreciated.

Create and post a simple test case that demonstrates the issue in
isolation.

Richard.
 
V

VK

<script type="text/javascript">
Array.prototype.firstIndexOf = function(x) { // find first x in array
  for (var i=0, l=this.length; i<l; ++i) if (this === x) return i;
  return false;
  };
</script>

The plan is that then, any array will have an Array.firstIndexOf(x)
method.

However, and I suspect this is a closure issue, I start getting
unexpected "undefined" results when I add the array prototype definition,
even when not actually calling it.

So, it's not only not doing what I want, but it's also doing something
else that breaks previously working code. :(


You are having a sparse array where some elements are not initialized
or "initialized with undefined" (a strange feature Javascript allows
to do). In your previous code you used the "cheat code" like
for (var p in myArray) {...
so treated Array members as Object properties. Now you decided to work
with array length so sparse or no sparse it will go through the whole
array from one border to the other.
Just guessing...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top