Массивы JavaScript: различия между версиями
imported>Supportadmin (Новая страница: «==Массивы== ===push=== '''array.push( elem1, elem2, ... )''' Эти элементы будут добавлены в конец массива. Он д…») |
imported>Supportadmin |
||
| (не показано 6 промежуточных версий этого же участника) | |||
| Строка 1: | Строка 1: | ||
==Массивы== | ==Массивы== | ||
оригинал:http://javascript.ru/basic/array | |||
----- | |||
Javascript поддерживает два вида структуры "массив": | |||
Ассоциативный массив (хеш), где данные хранятся по произвольному ключу. (Об этом читайте в разделе [[Javascript объекты в примерах|Объекты]].) | |||
Числовой массив Array, где данные хранятся по номерам. Он описан в этой статье. | |||
Javascript - очень гибкий язык, поэтому технически в Array можно хранить произвольные ключи, как в Object. Но лучше использовать типы по назначению. | |||
Для хранения данных по номеру предназначен тип Array. | |||
var arr = new Array() | |||
arr.test = 5 | |||
arr[1] = "blabla" | |||
В типе Array есть специальные методы, ориентированные именно на работу с числовыми ключами. | |||
== Создание и изменение == | |||
Есть два эквивалентных способа создания массива: | |||
var a = new Array() | |||
var a = [] | |||
Или, сразу со значениями | |||
var a = new Array("a", 1, true) | |||
var a = ["a", 1, true] | |||
Эти способы работают одинаково, кроме объявления вида new Array(10), когда у конструктора есть единственный аргумент-число. | |||
Такое объявление создаст пустой массив (все элементы undefined) длиной 10. По возможности, не используйте new Array. | |||
Отсчет элементов начинается с нуля: | |||
alert(a[0]) // => "a" | |||
Массив хранит данные по численным ключам, но внутри он использует точно такой же хэш (ту же структуру данных), как и обычный объект, поэтому можно сделать так: | |||
var a = [] | |||
a[1] = 1 | |||
a[999999] = 2 | |||
и массив a будет занимать память, нужную для хранения этих двух соответствий, а не займет длинный непрерывный кусок памяти, как это произошло бы в языке С. | |||
=== Авто-длина length === | |||
У каждого массива есть свойство length, которое автоматом меняется при каждом обновлении массива. Длина массива - это не количество элементов, а максимальный целый ключ + 1: | |||
alert(a.length) // всего 2 элемента, но выведет 1000000 | |||
Добавлять новый элемент можно эквивалентными вызовами | |||
a[a.length] = "new element" | |||
a.push("new element") | |||
=== Перебор элементов === | |||
Перебор элементов обычно (когда индексы непрерывные) осуществляется простым циклом: | |||
var arr = [ "array", "elements", "here" ] | |||
for(var i=0; i<arr.length; i++) { | |||
... сделать что-то с arr[i] ... | |||
} | |||
Если индексы - с разрывами, то перебор осуществляется так же, как в объектах: | |||
var arr = [] | |||
arr[1] = 123 | |||
arr[9999] = 456 | |||
for(var i in arr) { | |||
if (!arr.hasOwnProperty(i)) continue; | |||
... сделать что-то с arr[i] ... | |||
} | |||
==Методы массивов== | |||
===push=== | ===push=== | ||
| Строка 48: | Строка 122: | ||
Добавляет в начало массива элементы и возвращает получившуюся длину.Добавленные элементы сохранят порядок следования. Данный метод изменяет исходный массив. | Добавляет в начало массива элементы и возвращает получившуюся длину.Добавленные элементы сохранят порядок следования. Данный метод изменяет исходный массив. | ||
<nowiki> | |||
var arr = ["a", "b"] | var arr = ["a", "b"] | ||
unshifted = arr.unshift(-2, -1); | unshifted = arr.unshift(-2, -1); | ||
alert(arr ); // [ -2, -1, "a", "b"] | alert(arr ); // [ -2, -1, "a", "b"] | ||
alert("New length: " + unshifted); // 4 | alert("New length: " + unshifted); // 4</nowiki> | ||
===Организация очереди | === slice === | ||
slice(begin[, end]) | |||
Возвращает подмассив с индексами begin…end. | |||
=== splice === | |||
splice(index, deleteCount[, element1,…, elementN]) | |||
Удалить deleteCount элементов, начиная с index, и вставить на их место element1…elementN | |||
Есть и еще много методов: | |||
join | |||
reverse | |||
... | |||
О них можно почитать на английском, например, в http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array | |||
==Организация очереди== | |||
<nowiki>/* | <nowiki>/* | ||
| Строка 140: | Строка 235: | ||
}</nowiki> | }</nowiki> | ||
==Очередь с одновременным выполнением нескольких заданий== | |||
Модуль использует Backbone.Events для оповещения о ходе выполнения задач и несколько полезных функций из Underscore. Экспорт объекта выполняется через [https://github.com/mistakster/app-skeleton/blob/master/app-skeleton.js мой фреймворк]. | Модуль использует Backbone.Events для оповещения о ходе выполнения задач и несколько полезных функций из Underscore. Экспорт объекта выполняется через [https://github.com/mistakster/app-skeleton/blob/master/app-skeleton.js мой фреймворк]. | ||
| Строка 232: | Строка 328: | ||
}()); | }()); | ||
Очередь конфигурируется с помощью одного обязательного параметра limit, который задает количество одновременно выполняемых задач. | Очередь конфигурируется с помощью одного обязательного параметра limit, который задает количество одновременно выполняемых задач. | ||
| Строка 256: | Строка 353: | ||
Контекстом во всех событиях выступает объект, который ставился в очередь. | Контекстом во всех событиях выступает объект, который ставился в очередь. | ||
== Очередь + стек == | |||
В массиве есть всё необходимое, чтобы работать с ним как с очередью или со стеком, или и с тем и другим одновременно. | |||
Методы push и pop добавляют или вынимают значение с конца массива | |||
var arr = [3,5,7] | |||
arr.push(9) | |||
var last = arr.pop() //= 9 | |||
var last = arr.pop() // = 7 | |||
alert(arr.length) // = 2 | |||
Методы shift/unshift делают то же самое, с начала массива. | |||
var arr = [4,6,8] | |||
arr.unshift(2) // arr = [2,4,6,8] | |||
arr.unshift(0) // arr = [0,2,4,6,8] | |||
var last = arr.shift() // last = 0, arr = [2,4,6,8] | |||
arr.shift() // arr = [4,6,8] | |||
shift/unshift обычно приводят к перенумерации всего массива. shift сдвигает все элементы на единицу влево, а unshift - вправо. Поэтому на больших массивах эти методы работают медленнее, чем push/pop. | |||
Текущая версия от 12:37, 4 августа 2013
Массивы
оригинал:http://javascript.ru/basic/array
Javascript поддерживает два вида структуры "массив":
Ассоциативный массив (хеш), где данные хранятся по произвольному ключу. (Об этом читайте в разделе Объекты.)
Числовой массив Array, где данные хранятся по номерам. Он описан в этой статье.
Javascript - очень гибкий язык, поэтому технически в Array можно хранить произвольные ключи, как в Object. Но лучше использовать типы по назначению.
Для хранения данных по номеру предназначен тип Array.
var arr = new Array() arr.test = 5 arr[1] = "blabla"
В типе Array есть специальные методы, ориентированные именно на работу с числовыми ключами.
Создание и изменение
Есть два эквивалентных способа создания массива:
var a = new Array() var a = []
Или, сразу со значениями
var a = new Array("a", 1, true)
var a = ["a", 1, true]
Эти способы работают одинаково, кроме объявления вида new Array(10), когда у конструктора есть единственный аргумент-число.
Такое объявление создаст пустой массив (все элементы undefined) длиной 10. По возможности, не используйте new Array.
Отсчет элементов начинается с нуля:
alert(a[0]) // => "a"
Массив хранит данные по численным ключам, но внутри он использует точно такой же хэш (ту же структуру данных), как и обычный объект, поэтому можно сделать так:
var a = [] a[1] = 1 a[999999] = 2
и массив a будет занимать память, нужную для хранения этих двух соответствий, а не займет длинный непрерывный кусок памяти, как это произошло бы в языке С.
Авто-длина length
У каждого массива есть свойство length, которое автоматом меняется при каждом обновлении массива. Длина массива - это не количество элементов, а максимальный целый ключ + 1:
alert(a.length) // всего 2 элемента, но выведет 1000000
Добавлять новый элемент можно эквивалентными вызовами
a[a.length] = "new element"
a.push("new element")
Перебор элементов
Перебор элементов обычно (когда индексы непрерывные) осуществляется простым циклом:
var arr = [ "array", "elements", "here" ]
for(var i=0; i<arr.length; i++) {
... сделать что-то с arr[i] ...
}
Если индексы - с разрывами, то перебор осуществляется так же, как в объектах:
var arr = []
arr[1] = 123
arr[9999] = 456
for(var i in arr) {
if (!arr.hasOwnProperty(i)) continue;
... сделать что-то с arr[i] ...
}
Методы массивов
push
array.push( elem1, elem2, ... )
Эти элементы будут добавлены в конец массива. Он добавляет элементы, начиная с текущей длины length и возвращает новую, увеличенную длину массива.
Пример: добавление двух элементов
// array.length = 2
var array = [ "one", "two" ]
// добавить элементы "three", "four"
var pushed = array.push("three", "four")
// теперь array = [ "one", "two", "three", "four" ]
// array.length = 4
// pushed = 4
pop
arrayObj.pop()
Этот метод извлекает последний элемент массива и возвращает его. При этом возвращенный элемент удаляется из массива, а длина массива уменьшается на единицу. Если массив пустой, то метод pop() возвращает значение undefined, при этом массив так и остается пустым.
Этот метод изменяет исходный массив.
myFish = ["angel", "clown", "mandarin", "surgeon"]; popped = myFish.pop(); // теперь popped = "surgeon" // myFish = ["angel", "clown", "mandarin"]
shift
var elem = arrayObj.shift()
Удаляет элемент с индексом 0 и сдвигает остальные элементы на один вниз. Возвращает удаленный элемент
var arr = ["мой","маленький", "массив"] var my = arr.shift() // => "мой" alert(arr[0]) // => "маленький" // теперь arr = ["маленький", "массив"]
unshift
arrayObj.unshift( [elem1[, elem2[, ...[, elemN]]]] )
Аргументы
elem1, elem2, ..., elemN
Добавляет в начало массива элементы и возвращает получившуюся длину.Добавленные элементы сохранят порядок следования. Данный метод изменяет исходный массив.
var arr = ["a", "b"]
unshifted = arr.unshift(-2, -1);
alert(arr ); // [ -2, -1, "a", "b"]
alert("New length: " + unshifted); // 4
slice
slice(begin[, end]) Возвращает подмассив с индексами begin…end.
splice
splice(index, deleteCount[, element1,…, elementN]) Удалить deleteCount элементов, начиная с index, и вставить на их место element1…elementN
Есть и еще много методов:
join reverse ... О них можно почитать на английском, например, в http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array
Организация очереди
/*
Queue.js
A function to represent a queue
Created by Stephen Morley - http://code.stephenmorley.org/ - and released under
the terms of the CC0 1.0 Universal legal code:
http://creativecommons.org/publicdomain/zero/1.0/legalcode
*/
/* Creates a new queue. A queue is a first-in-first-out (FIFO) data structure -
* items are added to the end of the queue and removed from the front.
*/
function Queue(){
// initialise the queue and offset
var queue = [];
var offset = 0;
/* Returns the length of the queue.
*/
this.getLength = function(){
// return the length of the queue
return (queue.length - offset);
}
/* Returns true if the queue is empty, and false otherwise.
*/
this.isEmpty = function(){
// return whether the queue is empty
return (queue.length == 0);
}
/* Enqueues the specified item. The parameter is:
*
* item - the item to enqueue
*/
this.enqueue = function(item){
// enqueue the item
queue.push(item);
}
/* Dequeues an item and returns it. If the queue is empty then undefined is
* returned.
*/
this.dequeue = function(){
// if the queue is empty, return undefined
if (queue.length == 0) return undefined;
// store the item at the front of the queue
var item = queue[offset];
// increment the offset and remove the free space if necessary
if (++ offset * 2 >= queue.length){
queue = queue.slice(offset);
offset = 0;
}
// return the dequeued item
return item;
}
/* Returns the item at the front of the queue (without dequeuing it). If the
* queue is empty then undefined is returned.
*/
this.peek = function(){
// return the item at the front of the queue
return (queue.length > 0 ? queue[offset] : undefined);
}
}
Очередь с одновременным выполнением нескольких заданий
Модуль использует Backbone.Events для оповещения о ходе выполнения задач и несколько полезных функций из Underscore. Экспорт объекта выполняется через мой фреймворк.
/**
* Queue for simultaneous task execution.
* Execution method MUST return the promise object.
*
* @param limit {Integer} number of simultaneous tasks
* @event schedule
* @event before
* @event after
*/
(function () {
var Task = function (obj, execMethod) {
_.extend(this, {
id: _.uniqueId("queueitem-"),
obj: obj,
execMethod: execMethod,
active: false
});
};
_.extend(Task.prototype, {
run: function () {
var func, value;
this.active = true;
func = this.obj[this.execMethod];
if (_.isFunction(func)) {
value = func.call(this.obj);
}
// return promise object
return value;
}
});
function runTasks() {
var activeTasks = _.filter(queue, function (task) {
return task.active;
});
if (queue.length > 0 && activeTasks.length < limit) {
// we can run another task
var candidate = _.find(queue, function (task) {
return !task.active;
});
if (candidate) {
Q.trigger("before", candidate.obj);
var taskDfd = candidate.run();
Q.trigger("after", candidate.obj, taskDfd);
if (taskDfd) {
taskDfd.always(function () {
var i, id = candidate.id;
for (i = 0; i < queue.length; i++) {
if (queue[i].id === id) {
queue.splice(i, 1);
break;
}
}
runTasks();
});
}
// check tasks one more time
setTimeout(runTasks, 500);
}
}
}
var queue, limit;
var Q = _.extend({
init: function (opts) {
queue = [];
limit = opts.limit;
},
schedule: function (obj, execMethod) {
var task = new Task(obj, execMethod);
if (queue) {
queue.push(task);
Q.trigger("schedule", obj);
runTasks();
}
}
}, Backbone.Events);
App.namespace("App.Queue", Q);
}());
Очередь конфигурируется с помощью одного обязательного параметра limit, который задает количество одновременно выполняемых задач.
App.Queue.init({limit: 5});
var message, i;
for (i = 0; i < 20; i += 1) {
message = new Message("text " + i);
App.Queue.schedule(message, "delivery");
}
В этом примере будет сгенерировано 20 объектов сообщений, у которых есть метод delivery, реализующий всю работу по доставке этого сообщения. Они все будут сразу поставлены в очередь, но одновременно отправляться смогут только 5 сообщений.
После добавления задания в очередь генерируется событие schedule, а до и после запуска задачи — before и after соответственно. В событии after в качестве параметра передается promise-объект задачи. Через него можно так же отслеживать окончание её выполнения в другом модуле.
App.Queue.on("after", function (messagePromise) {
messagePromise.done(function () {
console.log("message " + this.get("id") + " was delivered");
});
messagePromise.fail(function () {
console.log("delivering message " + this.get("id") + " was failed");
});
});
Контекстом во всех событиях выступает объект, который ставился в очередь.
Очередь + стек
В массиве есть всё необходимое, чтобы работать с ним как с очередью или со стеком, или и с тем и другим одновременно.
Методы push и pop добавляют или вынимают значение с конца массива
var arr = [3,5,7] arr.push(9) var last = arr.pop() //= 9 var last = arr.pop() // = 7 alert(arr.length) // = 2
Методы shift/unshift делают то же самое, с начала массива.
var arr = [4,6,8] arr.unshift(2) // arr = [2,4,6,8] arr.unshift(0) // arr = [0,2,4,6,8] var last = arr.shift() // last = 0, arr = [2,4,6,8] arr.shift() // arr = [4,6,8]
shift/unshift обычно приводят к перенумерации всего массива. shift сдвигает все элементы на единицу влево, а unshift - вправо. Поэтому на больших массивах эти методы работают медленнее, чем push/pop.
