/    Sign up×
Community /Pin to ProfileBookmark

override Array object’s methods not working

Hi,

Since IE doesn’t support Array.shift() and Array.unshift(), I have to override them… but here is the problem, it works in firefox but NOT IE!

here is the code:

[CODE]
// Array.shift override
Array.prototype.shift = function() {
// Get the first value of array through ‘this’
var value = this[0];

for (var ndx = 1; ndx < this.length; ndx++) {
this[ndx – 1] = this[ndx];
}

// Return first value
return value;
};

// Array.unshift override
Array.prototype.unshift = function() {
// Get number of arguments
var nArgs = arguments.length;
var nElements = this.length;

for (var ndx = nElements – 1; ndx >= 0; ndx–) { this[ndx + nArgs] = this[ndx]; }
for (var ndx = 0; ndx < nArgs; ndx++) { this[ndx] = arguments[ndx]; }

// Return the new size of the array
return nElements += nArgs;
};
[/CODE]

For some reason, this code doesn’t work under IE. IE says that the object doesn’t support the method.

Any help is appreciated.

Crud

to post a comment
JavaScript

12 Comments(s)

Copy linkTweet thisAlerts:
@mrhooDec 12.2007 — Both Array.prototype.shift and unshift are defined in all modern browsers, including IE5+
Copy linkTweet thisAlerts:
@Arty_EffemDec 12.2007 — 
[CODE]
// Array.shift override
Array.prototype.shift = function() {
// Get the first value of array through 'this'
var value = this[0];

for (var ndx = 1; ndx < this.length; ndx++) {
this[ndx - 1] = this[ndx];
}

// Return first value
return value;
};

[/CODE]


For some reason, this code doesn't work under IE. IE says that the object doesn't support the method.
[/QUOTE]
I don't get that error, but your (unnecessary) implementation of [I]shift[/I] is flawed because it doesn't contract the array.
[CODE]this.length-=1;[/CODE]
Copy linkTweet thisAlerts:
@Crud_O_MaticauthorDec 12.2007 — I don't get that error, but your (unnecessary) implementation of [I]shift[/I] is flawed because it doesn't contract the array.
[CODE]this.length-=1;[/CODE][/QUOTE]


In firefox, you don't need to do this.length--; to contract the array, else this.length gets decremented by 2

weird stuff

everytime I access an array's shift and unshift methods in all versions of IE I get "Object doesn't support this property or method" even WITHOUT trying to override. That is why I'm trying to override the functions, as they don't work in IE. Also, I forgot to mention, this happens in Opera too.

Crud
Copy linkTweet thisAlerts:
@Arty_EffemDec 12.2007 — 
everytime I access an array's shift and unshift methods in all versions of IE I get "Object doesn't support this property or method" even WITHOUT trying to override. That is why I'm trying to override the functions, as they don't work in IE. Also, I forgot to mention, this happens in Opera too.
[/QUOTE]
Can you show a code example that doesn't work?[CODE]<script type='text/javascript'>

var testArray=[73,81,89,54,38,02,81,6];

testArray.shift();

alert(testArray);

testArray.unshift(73);

alert(testArray);

</script>[/CODE]
Copy linkTweet thisAlerts:
@Crud_O_MaticauthorDec 12.2007 — Ok,

I've found that the shift(); and unshift(); functs work in IE - now scratching head...

Why in my code does IE throw that error?

Here is the script entirely:
[CODE]
// Global Code out here by it's lonesome...

// System Object
var system = {
// init function
init: function() {
// Check & Set for one copy only - this is so init() always keeps the same state
if (arguments.callee._singletonInstance) { return arguments.callee._singletonInstance; }
arguments.callee._singletonInstance = this;
},

// browser detection and steering
browser: {
// store browser tests
ie: !!(window.attachEvent && !window.opera),
ie7: !!(window.attachEvent && !window.opera) && navigator.userAgent.indexOf('MSIE 7') > -1,
gecko: {
firefox: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 && navigator.userAgent.indexOf('Firefox') > -1,
ns6plus: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 && navigator.userAgent.indexOf('Netscape') > -1,
generic: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
},
opera: !!window.opera,
opera9: !!window.opera && navigator.userAgent.indexOf('Opera/9') > -1,
opera8: !!window.opera && navigator.userAgent.indexOf('Opera/8') > -1,
opera7: !!window.opera && navigator.userAgent.indexOf('Opera/7') > -1
},

// system queue (functions are queued and executed in a FIFO queue)
queue: {
// Processing flag (check it to see if queue is busy processing)
processing: false,
// Number of queue entries
entries: 0,
// The actual queue (FIFO style push/shift array)
queue: undefined,

// queueObject - an entry in the queue - contains queued functions and their arguments.
queueObject: function(funct, fowner, fargs) {
this.run = funct;
this.args = [];
this.owner = fowner;

if (typeof(fargs) == 'array' || typeof(fargs) == 'object' && fargs) {
this.args = fargs.slice(0);
} else if (fargs == null) {
this.args = [];
} else {
alert('You must pass an array representing function arguments to queueObject().');
return false;
}
},

// Add an entry to the queue
// Extra arguments other than the ones seen are considered function arguments and are put on the queue
// priority is ignored when process() is called with arguments
add: function(funct, fowner, fnice) {
// If queue array is NULL, initialize it
if (!this.queue) { this.queue = new Array(); }
// Check owner (queue entry owner - really just a name)
if (!fowner || fowner == null) { fowner = 'nobody'; }
// Check fnice (priority)
if (!fnice || fnice == null) { fnice = false; }

// Check the type of funct. If function, then put it in the queue.
if (typeof(funct) == 'function') {
// If the function has arguments, insert them
if (arguments.length > 3) {
// cast arguments into an array, and shift() off function call (1st. argument),
// owner (2nd. argument), and priority (3rd.)
var tmp_args = new Array();
tmp_args = Array.slice(arguments);
tmp_args.shift();
tmp_args.shift();
tmp_args.shift();

// Add function & args to queue
// if priority set then stick function & args to front of queue
if (!fnice) {
this.queue.push(new this.queueObject(funct, fowner, tmp_args));
} else {
this.queue.unshift(new this.queueObject(funct, fowner, tmp_args));
}
} else {
// Add function to queue
// if priority set then stick function to front of queue
if (!fnice) {
this.queue.push(new this.queueObject(funct, fowner, undefined));
} else {
this.queue.unshift(new this.queueObject(funct, fowner, undefined));
}
}

// increment queue entries counter
this.entries++;
} else {
// funct wasn't a function, warn user and return false.
alert('You must pass a function to system.queue.add().');
return false;
}
},

// Process the queue
// pass owner(s) to process just those scripts: process('owner', [owner2], ...);
// call bare to process whole queue: process();
process: function() {
// Recurse flag
if (!recurse) { var recurse = false; }

// Check to see if currently processing, if not, set processing flag to true (currently processing queue)
// If processing, see if queue is empty. If not, then process() was called recursively. Allow through.
// If queue is empty, reset processing flag and return true.
if (!this.processing && this.entries && !recurse) {
this.processing = true;
} else if (this.processing && !this.entries) {
recurse = false;
this.processing = false;
return true;
}

// Check if arguments where passed, if so then this is a request to
// process all the scripts owned by owner(s)
if (arguments.length) {
var tmp_args = Array.slice(arguments);

for (var ndx = 0; ndx < tmp_args.length; ndx++) {
for (var ndx2 = 0; ndx2 < this.queue.length; ndx2++) {
if (this.queue[ndx2].owner == tmp_args[ndx]) {
// Process queue...
// run directly from queue, then splice out
this.queue[ndx2].run.apply(this, this.queue[ndx2].args);
this.queue.splice(ndx2, 1);

// Decrement queue entries counter
this.entries--;
ndx--;
}
}
}

recurse = false;
this.processing = false;
return true;
}

// Process queue...
// shift off a function from queue, capture function in a local variable
var funct = this.queue.shift();

// Call function
funct.run.apply(this, funct.args);
// Discard function
delete funct;
// Decrement queue entries counter
this.entries--;

// Set recurse flag and recall process() recursively
recurse = true;
this.process();
}
},

// DOM manipulation
dom: {
// define doctypeObject for storing info about the DOCTYPE
doctypeObject: function() {
// Check & Set for one copy only - this is so this function always keeps the same state
if (arguments.callee._singletonInstance) { return arguments.callee._singletonInstance; }
arguments.callee._singletonInstance = this;

// Make cleaners
this.public_cleaner = /s+(X?HTML){1}s+([d.]+)s*([^/]+)/{2}([A-Za-z]{2})/gi;
// Public string
this.public = document.doctype.publicId;
// markup type - dealing with HTML or XHTML, version, etc...
this.public_cleaner.exec(document.doctype.publicId);
this.markup = {
id: RegExp.$1,
version: RegExp.$2,
guideline: RegExp.$3,
language: RegExp.$4
};
// the DTD
//this.dtd = somefuncttogetdtd();
}
}
};
[/CODE]


Here is the HTML required:

[CODE]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript" language="JavaScript" src="system.js"></script>
</head>

<body>

<span id="t1">Loading...</span><br />
<span id="t2">Loading...</span><br />
<span id="t3">Loading...</span>

<script type="text/javascript" language="JavaScript">
<!--
var tmp = 0;
function change(id) {
tmp++;
id = id + tmp;
document.getElementById(id).innerHTML = tmp + ' order - ' + arguments[1] + '<br>';
for (x = 0; x < 99999; x++) { }
}

function hey() {
alert('hello');
}

// Test Array before going into system object
var a = new Array();
a[0] = 1;
a.shift();

// Construct the system object
system.init();

// add functions to the queue:
// system.queue.add(funct, ownername, priority, [arg1], [arg2] ...);
// ownername is just a name of the function/code that made queue entry
// priority is a boolean value indicating where it is to be placed on queue:
// false = rear of queue(normal), true = front of queue(priority)
system.queue.add(change, 'wimpy', true, 't', 1);
system.queue.add(change, 'body', true, 't', 2);
system.queue.add(change, 'theman', false, 't', 3);
system.queue.add(hey);

// Process queue
// you can pass owner names to process to single those jobs out
// for immediate processing
system.queue.process();

// -->
</script>
</body>
</html>
[/CODE]


Can't figure out why the error is thrown.

Thanks in advance,

Crud
Copy linkTweet thisAlerts:
@felgallDec 12.2007 — Why are you testing a free format user definable field to decide what browser your visitor is using?
Copy linkTweet thisAlerts:
@toicontienDec 12.2007 — If you are going to override methods in the base classes of JavaScript, first ensure the method doesn't already exist:
if (!Array.shift) {
Array.prototype.shift = function() {
...
};
}

This ensures the native Array.shift method is used in complying browsers, and your override is only used for non-complying browsers. Native methods are always faster than ones you write.
Copy linkTweet thisAlerts:
@Crud_O_MaticauthorDec 12.2007 — Why are you testing a free format user definable field to decide what browser your visitor is using?[/QUOTE]

I assume you mean system.browser - in case there are browser specific things to be done.

Not exactly sure what you mean, maybe using navigator.userAgent?
Copy linkTweet thisAlerts:
@toicontienDec 12.2007 — It's best to use object detection instead of browser detection.
Copy linkTweet thisAlerts:
@Arty_EffemDec 12.2007 — 
if (!Array.shift) {
[/QUOTE]

That needs to be
[CODE]if (!Array().shift)
...[/CODE]
or it may return undefined.
Copy linkTweet thisAlerts:
@toicontienDec 12.2007 — Shoot, wrong syntax on my part:
if (!Array.[B]prototype.[/B]shift) {
Array.prototype.shift = function() {
...
};
}
Copy linkTweet thisAlerts:
@Crud_O_MaticauthorDec 16.2007 — [CODE]
var tmp_args = Array.slice(arguments);
[/CODE]


is the line that is erroring out now... very wierd stuff - FF is just fine, but IE & Opera both choke and say that the object doesn't support that method or property

Crud
×

Success!

Help @Crud_O_Matic spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 6.17,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @nearjob,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,
)...