如果使用javascript中的map方法在通过数组的循环执行过程中将元素推到数组上会发生什么

时间:2019-07-17 23:24:41

标签: javascript dictionary

在我的Web应用程序中:

  • 我有一个通过Firebase API实时更新的数组。
  • 我有一个用户触发的方法,虽然该数组可以循环 根据一些给定的参数检索元素。

如果使用javascript中的map方法在通过数组的循环执行过程中将元素推到数组上会发生什么?

或者换句话说,我可以假设使用map方法遍历数组时,map方法遍历数组快照吗?

我想避免使用df['a'] == 'foo' and pd.Series(df.index.isin(['2019-01-05','2019-01-09'])) 来确保我遍历快照。

任何人都可以提供可以测试此方案的代码吗?

1 个答案:

答案 0 :(得分:1)

您实际上不需要测试; The ECMAScript spec很清楚:

  

在第一次调用callbackfn之前设置map处理的元素的范围。调用map开始后追加到数组的元素将不会被callbackfn访问。如果更改了数组的现有元素,则传递给callbackfn的值将是映射访问它们时的值;在地图调用开始后被访问之前被删除的元素不会被访问。

如果要测试,可以使用类似以下的内容:

const arr = [5];

const result = arr.map( x => {
  console.log( `Visiting ${x}` );
  arr.push( x + 1 );
  return 2*x;
} );

console.log( arr ); // Has two elements

console.log( result ); // Only has one element

但是,当您说:

  

或者换句话说,我可以假设使用map方法遍历数组时,map方法遍历数组快照吗?

与您以前的措辞不同。映射回调不会访问被压入数组的元素,但是已替换的元素将成为其新值。您可以像这样测试:

const arr = [0,0];

const result = arr.map( x => {
  console.log( `Visiting ${x}` );
  arr[1] = 3;
  return 2*x;
} );

console.log( result );

注意:Array#map是同步的,并且JavaScript是单线程的,因此,如果回调中的代码没有使数组发生变化,则在迭代过程中就不可能使数组发生变化(其他代码,即IE firebase,无法在地图运行时运行。

const arr = [0,1,2,3,4,5];

// Change a random value in arr every 4 milliseconds
//    Emulates Firebase modifying the array
setInterval( function ( ) {
  arr[~~(Math.random()*6)] = Math.random( );
}, 4 );

// (async), Logs values after they've been modified
setTimeout( function ( ) {
  console.log( 'Logging array values after one second' );
  arr.map( x => console.log( x ) );
}, 1000 );

// Logs the values unmodified, async code, such as Firebase can't affect this
console.log( '(sync) with a 100ms spinlock between each map callback, to demonstrate that the array cannot be modified externally during the map.' );
arr.map( x => {
  console.log( x );
  const start = +new Date;
  while( +new Date < start + 100 ); // Wait for 100 milliseconds
} );