簡體   English   中英

精通 Javascript 的人可以簡單地向我解釋這里發生了什么

[英]Can someone fluent in Javascript explain to me whats going on here SIMPLY

我正在上 udemy 的課程,我遇到了這段更改窗口背景的代碼。 問題是函數 randColor 失去了我。 我想知道到底是怎么回事。

我知道聲明了一個名為 randColor 的函數,然后函數本身返回一個函數 + # 但我試圖理解這一切發生的邏輯。 添加了一個 HASH 符號,我相信它也是一個 IIFE 正確嗎?

我非常感謝您的幫助!

document.querySelector("button").addEventListener("click", function(){
  document.body.style.background = randColor();
})


function randColor(){
  return '#' + (function co(lor){   return (lor +=
    [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'][Math.floor(Math.random()*16)])
    && (lor.length == 6) ?  lor : co(lor); })('');
}

目標是生成十六進制格式的隨機顏色。 我試圖解釋您提供給我們的代碼:

randColor被調用時,它被添加到調用堆棧中,然后暫停等待嵌套函數的調用完成。

嵌套函數co(lor)是 IIFE,它被遞歸調用。 最初傳入一個空字符串,並為其分配局部lor變量。

Math.floor(Math.random()*16) - 生成從 0 到 15 的數字,它們是數組[0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']的索引[0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'] 在每一步,數組中的一個新符號被添加到先前作為參數傳入的本地lor字符串中。 如果長度小於 6,更新的字符串將進一步傳遞到新的調用中。

嵌套函數的遞歸添加到具有lor值的調用堆棧對象中(例如):

5aTh46 (top, last call, gets popped out first)
5aTh4
5aTh
5aT
5a
5      (first call)

當第 6 次調用后局部lor變量的長度等於 6 時,則滿足基本條件lor.length == 6並且從調用堆棧的頂部返回5aTh46字符串。 所以,對於第 5 次調用,我們有

return (lor += [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'] [Math.floor(Math.random()*16)]) && (lor.length == 6) ? lor /* = 5aTh4*/ : co(lor) /* = 5aTh46*/;

lor.length == 6為假,因為本地lor等於5aTh4 因此,第 6 次調用返回的5aTh46第 5 次調用之后返回,依此類推,直到作為co(lor)調用的結果最終返回值5aTh46並添加到randColor#字符串。 最后我們得到#5aTh46

附注。 我是這樣理解的。 如果您了解事件循環IIFE的概念, 那么這個解釋可能聽起來很簡單:)

是的。 它是一個IIFE 調用以''開頭。 然后進行遞歸調用,從數組[0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']一次追加 1 個字符[0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']隨機。 添加了六個這樣的字符(由(lor.length == 6)檢查)。 前面的 '#' 附加到 6 個字符以形成隨機顏色,該顏色由函數randColor()返回。

(function co(lor /* passed empty string */){ /* concatenate result of `co("")` */  return (lor +=
    [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'][Math.floor(Math.random()*16)])
       // if `lor` string `.length` is `6` return `lor` string 
       // else call `co` with `lor` as parameter
    && (lor.length == 6) ?  lor : co(lor); })('' /* empty string */)

代碼起初看起來很糟糕。 讓我們一步一步地簡化它。

//find 1st <button> element and assign on'click' handler to it
document.querySelector("button").addEventListener("click", function(){
  document.body.style.background = randColor();
  //background is the **result** of execution of randColor()
})


function randColor(){
  return '#' + (function co(lor){   return (lor +=
    [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'][Math.floor(Math.random()*16)])
    && (lor.length == 6) ?  lor : co(lor); })('');
}

randColor()返回一個包含函數的表達式(實際上是IIFE )。
讓結果而不是函數調用。 同時,由於前面的+運算符,這里可以省略函數周圍的括號。

document.querySelector("button").addEventListener("click", function(){
  document.body.style.background = '#' + function co(lor){
   return (lor +=
    [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'][Math.floor(Math.random()*16)])
    && (lor.length == 6) ?  lor : co(lor); }(''/*send empty string to lor parameter*/);
})

還是不容易? 讓我們進行下一步。

document.querySelector("button").addEventListener("click", function(){
  document.body.style.background = '#' + co(''/*send empty string to lor parameter*/);
})

function co(lor){
   return (lor += /*assignment returns the new value. always truey in this case*/
    [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'][Math.floor(Math.random()*16)/*magic 16 is the array length*/])
    && (lor.length == 6) ?  /*returns when we have 6 character string*/lor : /*call the function recursively*/co(lor); 
}

和最后的簡化。 使用循環而不是遞歸。

function co(){
   var lor = '';
   var hexDigits = '0123456789abcdef'.split('');
   for(var i = 0; i < 6/*required length*/;i++){
     lor += hexDigits[Math.floor(Math.random() * 16)/*0 - 15*/];
   }
   return lor;
}

前導#構成顏色的正確HEX值。

我想提出一個更簡化的迭代代碼而不是遞歸。

   <script type="text/javascript">
    document.querySelector("button").addEventListener("click", function(){
        // body
        document.body.style.background=randcolor();
    })

    function randcolor(){

        var list=['1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f'];
        var r='#';
        while(r.length<7)
        {
            r+=list[Math.floor(Math.random()*16)];
        }
        return r;
    }

</script>

"#" 是顏色代碼 (#7b7b6e) 的一部分,該函數返回一個類似於 "7b7b6e" 的隨機字符串,並在其前面添加 #

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM