[英]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
。 調用以''
開頭。 然后進行遞歸調用,從數組[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.