Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > BuKT

Оценить эту запись

forEach. Вскрытие

Запись от BuKT размещена 14.04.2011 в 04:37

Это интересно. В ActionScript 3.0 действует хитрое хеширование значений. Даже при условии ссылочности переменных, не всегда изменение значения переменной приведёт к мгновенному изменению значений переменных, ссылающихся на исходную.

Например - forEach. Следующий код предназначен для наращивания значений массива до единицы для array[array.length - 1] (при исходной сумме всех значений в единицу). Вероятности, короче, рассчитывает:
Код AS3:
probsArray.forEach(function(e:Number,i:int,arr:Array){
  if (i > 0) {
    e += arr[i-1];
  }
  trace (i + ': ' + e);
});
В случае с исходным [0.2,0.2,0.2,0.2,0.2] выведет
Код AS3:
0: 0.2
1: 0.4
2: 0.4
3: 0.4
4: 0.4
Результирующий массив будет аналогичным
Понятно, что происходит? При каждом запросе значений массива внутри коллбека функции forEach — `arr` возвращает кешированное значение, т.к. фактическое присвоение каждому элементу `e` наращиваемого значения происходит по закрытию всех коллбеков. И запрашивая arr[i-1] мы запрашиваем не `e` из прошлой итерации, а неизменённое исходное значение этого элемента массива.

Поэтому, если мы хотим в этой же (или в любой последующей) итерации получить изменённое значение: изменять значения элементов массива следует по прямой ссылке на них (вместо изменения внутренней переменной `e` метода forEach). Примерно так:

Код AS3:
probsArray.forEach(function(e:Number,i:int,arr:Array){
  if (i > 0) {
    arr[i] += arr[i-1];
  }
  trace (i + ': ' + arr[i]);
});
//0: 0.2
//1: 0.4
//2: 0.6000000000000001 //Из-за особенностей обсчёта Number во FlashPlayer
//3: 0.8
//4: 1
Всего комментариев 5

Комментарии

Старый 14.04.2011 11:51 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Я ничего не понял - что значит кешированное значение?. В метод просто передается элемент массива (я про параметр e). В примере это тип Number - т.е. примитивный тип, что означает что имеем копию объекта, а не ссылку на него. Естественно что меняя это значение никаким образом не повлечет за собой изменения в массиве.
Старый 14.04.2011 12:19 gloomyBrain вне форума
gloomyBrain
 
Аватар для gloomyBrain
Меня больше всего удивляет то, что и String тоже является примитивным типом. А с числами оно, по-моему, везде так: передача идет не по ссылке, а по значению.
Старый 14.04.2011 12:20 Котяра вне форума
Котяра
 
Аватар для Котяра
Алхимик придумывает теорию про животворящий эфир.
Старый 14.04.2011 12:44 BuKT вне форума
BuKT
 
Аватар для BuKT
Сорри, писалось в пять утра после долгого мозгообмывательства. Если получится - исправлю на что-то более удобочитаемое
Старый 18.12.2011 15:45 expl вне форума
expl
Цитата:
Меня больше всего удивляет то, что и String тоже является примитивным типом. А с числами оно, по-моему, везде так: передача идет не по ссылке, а по значению.
Впринципе, он не совсем примитивен и, впринципе, передается по ссылке.
Просто его нельзя менять. Можно только создать новую строку.
В Java/С# тоже поменять строку нельзя.

Числа при кодинге тоже можно считать объектами, которые не меняются, например:
Код AS3:
x = 2 + 3;//Создалось новое число 5
Только на уровне виртуальной машины их нет смысла передавать по ссылке - они весят столько же сколько сама ссылка.

Код AS3:
probsArray.forEach(function(e/*=.2*/:Number,i:int,arr:Array){
  if (i > 0) {
    e/*=.2*/ += arr[i-1]/*=.2*/;
  }
  trace (i + ': ' + e)/*.2 + .2 = .4 для всех i > 0*/;
});
По-моему, все объясняется без всяких "теорий кеширования". Меняем ведь локальную переменную e, а не переменную контекста, захваченную замыканием или другую, глобальную по отношению к анонимной функции.
Обновил(-а) expl 18.12.2011 в 15:58
 

 


Часовой пояс GMT +4, время: 12:34.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.