forEach. Вскрытие

Apr 14, 2011 06:27

<6:12>

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

Например - forEach. Следующий код предназначен для наращивания значений массива до единицы для array[array.length - 1] (при исходной сумме всех значений в единицу). Вероятности, короче, рассчитывает:

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] выведет

0: 0.2
1: 0.4
2: 0.4
3: 0.4
4: 0.4Результирующий массив будет аналогичным
Понятно, что происходит? При каждом запросе значений массива внутри коллбека функции forEach - `arr` возвращает кешированное значение, т.к. фактическое присвоение каждому элементу `e` наращиваемого значения происходит по закрытию всех коллбеков. И запрашивая arr[i-1] мы запрашиваем не `e` из прошлой итерации, а неизменённое исходное значение этого элемента массива.

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

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

особенности AS 3.0

Previous post Next post
Up