Я не думаю, что это действительно противоречивы. Да, они могут быть немного запутанными, поскольку массивы JavaScript делают все то, для чего другие языки имеют отдельные структуры (список, очередь, стек, ...), но их определение довольно согласовано между языками. Вы можете легко группировать их в этих категориях вы уже описывались:
- список методы:
push
/unshift
возвращают длину после добавления элементов
pop
/shift
возвращения запрашиваемого элемента
- можно определить дополнительные методы получения первого и последнего элемента, но они редко необходимы
splice
- универсальный инструмент для удаления/замены/вставки элементов в середине списка - он возвращает массив удаленных элементов.
sort
и reverse
- два стандартных метода переупорядочения на месте.
Все остальные методы не изменяют исходный массив:
slice
получить подмассив положения, filter
, чтобы получить их состояния и concat
сочетать с другими создавать и возвращать новые массивы
forEach
просто выполняет итерацию массива и ничего не возвращает
every
/some
проверить элементы состояния, indexOf
и lastIndexOf
se arch для элементов (по принципу равенства) - оба возвращают свои результаты
reduce
/reduceRight
уменьшают элементы массива до одного значения и возвращают их. Особые случаи:
map
сводится к новый массив - это как forEach
но возвращающие результаты
join
и toString
сводятся к строке
Эти методы являются достаточно для большинства наши потребности. Мы можем делать с ними все, и я не знаю никаких библиотек, которые бы добавляли к ним похожие, но внутренние или результирующие методы. Большинство библиотек обработки данных (например, Underscore) делают их только кросс-браузерными (es5-shim) и предоставляют дополнительные полезные методы.
Я хочу, чтобы всегда мутировать массив и всегда возвращал один и тот же массив, поэтому я могу иметь некоторую консистенцию и также иметь возможность цепочки.
Я бы сказал, что согласованность JavaScript заключается в том, чтобы всегда возвращать новый массив при изменении элементов или длины. Я предполагаю, что это потому, что объекты являются опорными значениями, а их изменение слишком часто вызывает побочные эффекты в других областях, которые ссылаются на один и тот же массив.
Chaining еще можно с этим, вы можете использовать slice
, concat
, sort
, reverse
, filter
и map
вместе, чтобы создать новый массив, только один шаг. Если вы хотите, чтобы «изменить» только массив, вы можете просто передать его в переменную массива:
A = A.slice(0,1).reverse().concat(['a','b']);
методы Мутации имеют только одно преимущество для меня: они быстрее, потому что они могут быть более эффективно использует память (зависит на реализацию и сборку мусора, конечно). Поэтому позволяет реализовать некоторые методы для них. Как Array subclassing является ни возможным, ни полезным, я определю их на native prototype:
var ap = Array.prototype;
// the simple ones:
ap.each = function(){ ap.forEach.apply(this, arguments); return this; };
ap.prepend = function() { ap.unshift.apply(this, arguments); return this; };
ap.append = function() { ap.push.apply(this, arguments; return this; };
ap.reversed = function() { return ap.reverse.call(ap.slice.call(this)); };
ap.sorted = function() { return ap.sort.apply(ap.slice.call(this), arguments); };
// more complex:
ap.shorten = function(start, end) { // in-place slice
if (Object(this) !== this) throw new TypeError();
var len = this.length >>> 0;
start = start >>> 0; // actually should do isFinite, then floor towards 0
end = typeof end === 'undefined' ? len : end >>> 0; // again
start = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
end = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
ap.splice.call(this, end, len);
ap.splice.call(this, 0, start);
return this;
};
ap.restrict = function(fun) { // in-place filter
// while applying fun the array stays unmodified
var res = ap.filter.apply(this, arguments);
res.unshift(0, this.length >>> 0);
ap.splice.apply(this, res);
return this;
};
ap.transform = function(fun) { // in-place map
if (Object(this) !== this || typeof fun !== 'function') throw new TypeError();
var len = this.length >>> 0,
thisArg = arguments[1];
for (var i=0; i<len; i++)
if (i in this)
this[i] = fun.call(thisArg, this[i], i, this)
return this;
};
// possibly more
Теперь вы можете сделать
A.shorten(0, 1).reverse().append('a', 'b');
Пример, который вы предоставили - 'A.slice (0,1) .reverse() Foreach (функция() {});' - работает, как ожидалось.. Я не уверен, какова ваша точка с этим примером. Вы заявляете, что хотели бы иметь возможность цепочки, а затем вы приводите пример с цепочкой с использованием существующих методов, который работает. Просьба привести примеры, которые * не * работают с существующими методами, чтобы я мог понять, что вы могли бы написать. –
@ ŠimeVidas нет, потому что 'slice' не мутирует массив, как я хочу, - он возвращает новый массив. Я могу привести больше примеров, если это поможет – David
Может быть, underscore.js? –