我参加了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); })('');
}
答案 0 :(得分:4)
目标是以十六进制格式生成随机颜色。我尝试解释您提供给我们的代码:
当调用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']
的索引。在每个步骤中,数组中的新符号将添加到先前作为参数传入的本地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
为false,因为本地lor
等于5aTh4
。因此,第5次调用返回的5aTh46
也会在第5次调用后返回,因此,5aTh46
的调用最终会返回直至co(lor)
的值,并添加到#
{1}} randColor
内的字符串。最后我们得到#5aTh46
。
PS。这就是我理解它的方式。如果你得到event loop和IIFE的概念,这个解释可能听起来很简单:)
答案 1 :(得分:0)
是。这是一个IIFE
。调用以''
开头。然后进行递归调用,从数组[0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']
中随机追加1个字符。添加了六个这样的字符(由(lor.length == 6)
检查)。前面的“#”前置于6个字符,形成随机颜色,由函数randColor()
返回。
答案 2 :(得分:0)
(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 */)
答案 3 :(得分:0)
起初的代码看起来很糟糕。让我们一步一步地简化它。
//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
颜色值。
答案 4 :(得分:0)
我想提出一个更简化的迭代代码,而不是递归。
<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>
答案 5 :(得分:-3)
“#”是颜色代码的一部分(#7b7b6e),该函数返回一个类似于“7b7b6e”的随机字符串,并在其前面添加#