为何两段ECMAScript随机打乱数组代码执行效果不同?
数组打乱代码执行效果差异解析
嘿,我来帮你理清楚这两段代码为啥执行效果完全不一样——核心问题出在是否真正修改了原数组的元素上:
第一段代码:看似交换,实则没碰原数组
先把代码格式化得更易读:
function randomize(arr){ for(var i = 0; i < arr.length; i++){ const random = Math.floor(Math.random()*arr.length); // 把数组元素的值复制到临时变量里 let temp = arr[i]; let newR = arr[random]; // 交换的只是两个临时变量的值,和原数组无关! [temp, newR] = [newR, temp]; } return arr; } console.log(randomize([1,2,3,4,5]));
这里的关键是:temp和newR是原数组元素值的副本(因为数组里存的是数字这种原始类型,赋值时会直接复制值)。你交换这两个临时变量,就像把盘子里的两个蛋糕拿出来换了个手,但根本没放回盘子里——原数组的元素位置从头到尾都没变化。所以这段代码执行后,输出的数组几乎和输入完全一致。
第二段代码:真正交换了数组元素位置
再看这段格式化后的代码:
function randomize(arr){ for(var i = 0; i < arr.length; i++){ const random = Math.floor(Math.random()*arr.length); // 直接操作数组的索引,交换两个位置的元素本身 [arr[i], arr[random]] = [arr[random], arr[i]]; } return arr; } console.log(randomize([1,2,3,4,5]));
这里是直接针对数组的索引位置进行操作:arr[i]和arr[random]指向的是数组里的具体元素位置,交换它们就相当于直接在盘子里把两个蛋糕换了位置,原数组自然会被修改,也就实现了打乱数组的效果。
小补充:顺便提一句,第二段的洗牌方式其实不是完全公平的(属于有偏洗牌),如果要实现无偏的随机打乱,推荐用标准的Fisher-Yates洗牌算法,但这是额外的知识点啦~
内容的提问来源于stack exchange,提问作者buzz eclair
相关产品推荐
相关产品推荐

