// @kangax fix yur SubArray (ES5 flavor) kthxbai
// http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/#ecmascript_5_accessors_to_the_rescue
// (C) Juriy Zaytsev (aka @kangax) - MIT Style License
// http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
var SubArray = (function() {
var MAX_SIGNED_INT_VALUE = Math.pow(2, 32) - 1,
hasOwnProperty = {}.hasOwnProperty,
isArray = function(v) { return toString.call(v) == '[object Array]'; },
slice = [].slice,
toString = {}.toString;
function getMaxIndex(object) {
var key, index, maxIndex = 0;
for (key in object) {
index = key >>> 0;
if (index === +key &&
index < MAX_SIGNED_INT_VALUE &&
index > maxIndex &&
hasOwnProperty.call(object, key)) {
maxIndex = index;
}
}
return maxIndex;
}
function isArrayLike(object) {
return object && (isArray(object) || object.constructor == SubArray);
}
function makeSubArray() {
var length = 0;
return Object.create(SubArray.prototype, {
'length': {
'get': function() {
var maxIndex = getMaxIndex(this);
return Math.max(length, maxIndex && maxIndex + 1);
},
'set': function(value) {
var uint = value >>> 0,
i = uint - 1, oldLen = this.length;
if (uint !== +value) {
throw new RangeError;
}
while (++i < oldLen) {
delete this[i];
}
length = uint;
}
}
});
}
function SubArray(length) {
var result = makeSubArray(), argLen = arguments.length;
if (argLen) {
if (argLen === 1 && typeof length === 'number') {
result.length = length;
} else {
result.push.apply(result, arguments);
}
}
return result;
}
if (typeof Array.isArray == 'function' && Array.isArray([]) === true) {
isArray = Array.isArray;
}
SubArray.prototype = [];
SubArray.prototype.constructor = SubArray;
SubArray.prototype.toString = SubArray.prototype.toLocaleString = Array.prototype.join;
SubArray.prototype.concat = function() {
var item, itemLen, j, i = -1,
length = arguments.length,
object = Object(this),
result = isArrayLike(object) ? slice.call(object, 0) : [object],
n = result.length;
while (++i < length) {
item = arguments[i];
if (isArrayLike(item)) {
j = 0; itemLen = item.length;
for ( ; j < itemLen; j++, n++) {
if (j in item) result[n] = item[j];
}
} else {
result[n++] = item;
}
}
return result;
};
return SubArray;
})();
Created
July 19, 2010 04:34
-
-
Save kangax/481016 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Another enhancement could be to use define(Getter|Setter) when
Object.create
is not available. Thisconcat
also needs tests (preferably from ES5 suite). I'll look into it when I get a chance.