在學習vue移動端音樂項目時,看到一個打亂數組函數,感受頗有意思就記錄一下(意外發現:slice是個有趣的知識點)vue
原理:遍歷數組,(let i = 0; i < _arr.length; i++),從0-i之間隨機取一個數,與當前的arr[i]做交換,這樣就把數組洗的很亂es6
// 返回min和max之間的一個隨機數,包括min和max function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1) + min) // +1是保證能夠取到上限值 } // 洗牌函數 function shuffle(arr) { let _arr = arr.slice() // 下面會講到slice的特別之處 for (let i = 0; i < _arr.length; i++) { let j = getRandomInt(0, i) let t = _arr[i] _arr[i] = _arr[j] _arr[j] = t } return _arr } var arr = [0,1,2,3,4]; shuffle(arr);
打亂數組就是這麼簡單,下面讓咱們說說爲何要用slice處理一下,而不是直接用arr自己???數組
咱們在打亂數組後,必定但願的是返回一個新的打亂過的數組,原來的數組不發生變化。dom
由於數組是引用類型,因此不能直接操做原數組(arr)。咱們須要拷貝一份,將拷貝的數組(_arr)打亂以後return出去。
那麼問題來了,slice能作到操做拷貝後的數組(_arr)而不改變原數組(arr)嗎?
答案是:能作到一半函數
由於let _arr = arr.slice()
能將原數組(arr)的第一層深拷貝。學習
舉個栗子:code
let obj = [ { name:0, job:0 }, { name:1, job:1 }, { name:2, job:2 } ]; let copy = obj.slice(0); // 0可省略 copy[1].name = 10; // 改變第二層,對象的屬性name console.log(obj[1].name); // 10 console.log(copy[1].name); // 10 copy[2] = {name: 20,job: 20}; // 改變第一層,將整個對象替換成別的對象(改變copy[2]對象的內存指向) console.log(obj[2].name); // 2 console.log(copy[2].name); // 20
綜上,就很好理解爲何要用let _arr = arr.slice()
處理了。對象
注:es6的Object.assign
、解構賦值
;Array的concat、map、filter
也只會深拷貝對象(數組)的第一層。內存
附加一個更騷的打亂方式:get
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; var numbers_ = numbers.slice(); numbers_ = numbers_.sort(function(){ return Math.random() - 0.5});