forked from kangax/array_subclassing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsubarray.js
97 lines (84 loc) · 2.79 KB
/
subarray.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
var makeSubArray = (function(){
var MAX_SIGNED_INT_VALUE = Math.pow(2, 32) - 1,
hasOwnProperty = Object.prototype.hasOwnProperty;
function ToUint32(value) {
return value >>> 0;
}
function compareMaxIndex(object, index) {
if (index < -1 || (index + 1 !== MAX_SIGNED_INT_VALUE && hasOwnProperty.call(object, index + 1)))
return 1;
else if (index >= MAX_SIGNED_INT_VALUE || (index !== -1 && !hasOwnProperty.call(object, index)))
return -1;
else
return 0;
}
function getMaxIndexProperty(object, old_index) {
var index = old_index,
direction = interval = compareMaxIndex(object, old_index);
if (direction == 0)
return index;
// find low and high by searching from old_index by powers of 2
do {
old_index = index;
interval *= 2;
index += interval;
} while (compareMaxIndex(object, index) == direction);
var high = direction == 1 ? index : old_index;
var low = direction == 1 ? old_index : index;
if (high >= MAX_SIGNED_INT_VALUE)
high = MAX_SIGNED_INT_VALUE - 1;
if (low < -1)
low = -1;
// binary search (implementation from underscore's sortedIndex())
while (low < high) {
var mid = Math.floor((low + high) / 2);
// var mid = (low + high) >> 1; // returns negative results for numbers near MAX_SIGNED_INT_VALUE
compareMaxIndex(object, mid) == 1 ? low = mid + 1 : high = mid;
}
return low;
}
return function(methods) {
var length = 0;
methods = methods || { };
methods.length = {
get: function() {
return getMaxIndexProperty(this, length - 1) + 1;
},
set: function(value) {
var constrainedValue = ToUint32(value);
if (constrainedValue !== +value) {
throw new RangeError();
}
// optimizate for the common case where a built-in
// prototype is setting the length to what it really is after modifications
if (compareMaxIndex(this, value) == 0)
length = value;
var old_len = this.length;
for (var i = constrainedValue, len = old_len; i < len; i++) {
delete this[i];
}
// the hasOwnProperty() check allows sparse arrays to be made contiguous
// via setting the length after-the-fact
for (var i = old_len, len = constrainedValue; i < len; i++) {
if (!hasOwnProperty.call(this, i))
this[i] = undefined;
}
length = constrainedValue;
}
};
methods.toString = {
value: Array.prototype.join
};
return Object.create(Array.prototype, methods);
};
})();
function SubArray() {
var arr = makeSubArray();
if (arguments.length === 1) {
arr.length = arguments[0];
}
else {
arr.push.apply(arr, arguments);
}
return arr;
}