15.5.4.14 String.prototype.split(separator, limit)

2010-07-10

array String.prototype.split(separator:string|regexp|mixed, limit:uint|mixed=(2^32-1))

Create an array by splitting up this string value at every index seperator is found. If the resulting array has more elements than limit it is truncated to match limit. The matched separators are not returned unless they are part of a capturing group of a regular expression.

Note that separator may be a string or a regular expression. If not regex, it is coerced into a string.

If the separator is an empty string, empty regular expression or regular expression that matches the empty string the separator does not match the emptiness at the start or end of a string.

If the separator is a regular expression note that only the first match will be returned, even if further searching might return a longer string. The example given, "ab".split(/a*?/) matches ["a","b"] because a*? is a non-greedy search. So the empty string would satisfy it and it effectively splits on the empty string, not on "a". The second example, "ab".split(/a*/) matches ["","b"] because a* will match a (even though it could also match the empty string). Note that it will always apply the regex as long as it finds matches, the global flag is ignored. The previous only describes what actually qualifies as the matched separator.

If this value, after coercion to string, equals the empty string the length of the array depends on the seperator. If it would match the empty string, the returned array will have zero elements. Otherwise the empty string is returned.

If separator is a regular exression with capturing parentheses the captured results for each match will be added to the array, even if the captured value is undefined.

If separator is undefined then the result array contains just one array, the this value coerced to a string.

String.prototype.split.length = 2

Code: (Meta Ecma)
String.prototype.split = function(separator, limit){
CheckObjectCoercible(this);
var S = ToString(this);
var A = new Array;
var lengthA = 0;
if (limit === undefined) var lim = Math.pow(2,32)-1;
else var limt = ToUint32(limit);
var s = S.length;
var p = 0;
if (Type(separator) == 'Object' && separator.[[Class]] == "RegExp") var R = separator;
else var R = ToString(separator);
if (lim == 0) return A;
if (separator === undefined) {
A.[[DefineOwnProperty]]("0", PD{[[Value]]:S, [[Writable]]:true, [[Enumerable]]:true, [[Configurable]]:true}, false);
return A;
}
if (s == 0) {
// for splitmatch, see below
var z = SplitMatch(R,S,0); // returns MatchResult result (15.10.2.1)?
// "failure"
if (z !== undefined) return A;
A.[[DefineOwnProperty]]("0", PD{[[Value]]:S, [[Writable]]:true, [[Enumerable]]:true, [[Configurable]]:true}, false);
return A;
}
var q = p;
while (q != s) {
var z = SplitMatch(R, S, q);
if (z === undefined) ++q;
else {
// z must be a State
var e = z.endIndex;
var cap = z.captures;
if (e == p) ++q;
else {
var T = S.substring(p, q);
A.[[DefineOwnProperty]](ToString(lengthA), PD{[[Value]]:T, [[Writable]]:true, [[Enumerable]]:true, [[Configurable]]:true}, false);
++lengthA;
if (lengthA == lim) return A;
var p = e;
var i = 0;
while (i != cap) {
++i;
A.[[DefineOwnProperty]](ToString(lengthA), PD{[[Value]]:cap[i ], [[Writable]]:true, [[Enumerable]]:true, [[Configurable]]:true}, false);
++lengthA;
if (A.length == lim) return A;
}
q = p;
}
}
}
var T = S.substring(p, s);
A.[[DefineOwnProperty]](ToString(lengthA), PD{[[Value]]:T, [[Writable]]:true, [[Enumerable]]:true, [[Configurable]]:true}, false);
return A;
}

Abstract SplitMatch operation:
MatchResult|State|undefined SplitMatch(S:string, q:int, R:regexp|string)

Code: (Meta Ecma)
SplitMatch = function(S, q, R){
if (Type(R) == 'Object' && R.[[Class]] == "RegExp") return R.[[Match]](S, q);
// Type(R) must be "String"
var r = R.length;
var s = S.length;
if (q+r > s) return; // failure
for (var i=0; i var cap = [];
return new State(q+r, cap); 15.10.2.1
}