有人能说流利的Javascript向我解释在这里发生什么简单

时间:2017-10-01 19:01:46

标签: javascript function iife

我参加了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); })('');
}

6 个答案:

答案 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 loopIIFE的概念,这个解释可能听起来很简单:)

答案 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”的随机字符串,并在其前面添加#