Изначальной задачей было сделать так, чтобы функция splice могла принимать отрицательный второй аргумент и удалять значения в обратном направлении.
Допустим есть массив:
var arr = [0,1,2,3,4,5];
splice(3,1);
>[0,1,2,4,5]
splice(3,-1);
>[0,1,3,4,5]
Но потом всё пошло не так. По стандарту, первые 2 аргумента обязательны, но по факту движки допускают вызов только с первым аргументом, удаляя остаток массива. Дальше приключения продолжаются! Отсутствием второго аргумента считается только вызов функции с 1 аргументом splice(0), если же вызвать метод как splice(0,undefined), то второй аргумент будет принят за ноль! Более того, нулями становятся null и даже NaN! В общем-то так ведут себя и другие методы. Решил я сделать всё аргументы не обязательными, но вот как быть с NaN пока не знаю. Пока сделал что он тоже инициирует значения по умолчанию.
Потратил много времени и задача-то в общем не первой важности, стандартный splice тоже прекрасно справляется. Но сдаваться не хотелось и я всё же добил его! Назовём его пока что mySplice:
mySplice(array[, start, deleteCount, item1[, item2[, ...]]])
Все аргументы, кроме массива опциональны!
Это будет работать как
array.push(1, 2, 3);
mySplice(array, null, null, 1, 2, 3);
Удаление двух элементов с начала:
mySplice(array, null, 2);
or
mySplice(array, 0, 2); // Like original
Удаление двух элементов с конца:
mySplice(array, null, -2);
or
mySplice(array, -2, 2); // Like original
or
mySplice(array, Infinity, -2);
Оставление двух элементов в начале:
mySplice(array, 2); // Like original
or
mySplice(array, 2, null); // Not like original
or
mySplice(array, 2, Infinity); // Like original
Оставление двух элементов в конце:
mySplice(array, -2);
or
mySplice(array, -2, null);
or
mySplice(array, 0, array.length - 2); // Like original
Но отрицательные числа приводят к другому эффекту, который, при желании, можно исправить, новые элементы будут добавляться с другой стороны.
Добавит элементы перед оставшимися:
mySplice(array, -2, null, 1, 2, 3);
Добавит элементы после оставшихся:
mySplice(array, 0, array.length - 2, 1, 2, 3);
И другие возможности, которые можно понять по коду (который, к сожалению, получился не простым) или, если будет спрос, я опишу позже. isNumeric() и trunc() интегрированы, чтоб не создавать зависимостей. Жду советов по доработке. Вот сама функция:
function mySplice (arr, start, deleteCount) {
if (!Array.isArray(arr)) {
throw new Error('Argument is not an Array.');
}
var len = arr.length;
// isNumeric. Non numeric triggers default
if (!isNaN(parseFloat(start))) {
// Truncate
start = (start - start % 1) || (!isFinite(start) || start === 0 ? start : start < 0 ? -0 : 0);
} else {
start = null;
}
// isNumeric. Non numeric triggers default
if (!isNaN(parseFloat(deleteCount))) {
// Truncate
deleteCount = (deleteCount - deleteCount % 1) || (!isFinite(deleteCount) || deleteCount === 0 ? deleteCount : deleteCount < 0 ? -0 : 0);
} else {
deleteCount = null;
}
var s = start;
var dc = deleteCount;
if (start == null) {
if (deleteCount == null) {
s = len;
} else if (-len < deleteCount && deleteCount < 0) {
s = len + deleteCount;
dc = -deleteCount;
} else if (len <= deleteCount || deleteCount <= -len) { // 2
dc = len;
}
} else if (len <= start) {
if (deleteCount == null) {
dc = 0;
} else if (deleteCount <= -len) {
s = 0;
dc = len;
} else if (-len < deleteCount && deleteCount < 0) {
s = len + deleteCount;
dc = -deleteCount;
}
} else if (0 < start && start < len) {
if (deleteCount == null) {
dc = len - start;
} else if (-start < deleteCount && deleteCount < 0) {
s = start + deleteCount;
dc = -deleteCount;
} else if (deleteCount <= -start) {
dc = start;
s = 0;
}
} else if (start <= 0) {
if (deleteCount == null || len <= deleteCount) {
dc = len;
}
if (-len < start && start < 0) {
if (deleteCount == null || deleteCount <= -(len + start)) {
s = 0;
dc = len + start;
} else if (-(len + start) < deleteCount && deleteCount < 0) {
s = start + len + deleteCount;
dc = -deleteCount;
}
} else if (start <= -len) {
if (deleteCount == null) {
dc = 0;
}
}
}
// Arguments object may be not connected to locals
arguments[1] = s;
arguments[2] = dc;
var aProto = Array.prototype;
return aProto.splice.apply(arr, aProto.slice.call(arguments, 1))
}