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

会有一股神秘感。 提交于 2019-12-11 07:19:39

问题


Im taking a course on udemy and I came across this code that changes the background of a window. The thing is the function randColor loses me. Id like to know exactly whats going on.

I know a function called randColor is declared, then the function itself RETURNS a function + # but I am trying to understand the logic of how it all happens. There is a HASH symbol that is added and I believe its also an IIFE correct?

I very much appreciate the help!

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); })('');
}

回答1:


The goal is to generate a random color in the Hex format. My attempt to explain the code you provided us with:

When randColor is called it is added to the call stack and then gets paused waiting for the nested function's calls to complete.

That nested function co(lor) is IIFE and it is called recursively. Initially an empty string is passed in and the local lor variable is assigned to it.

Math.floor(Math.random()*16) - generates numbers from 0 to 15 which are the indexes of the array [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']. At each step a new symbol from the array is added to the local lor string passed in as a parameter earlier. Updated string is passed further into a new call if its length is fewer than 6.

The nested function's recursion adds to the call stack objects with lor values like this (for example):

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

when the length of the local lor variable gets equal to 6 after the 6th call, then base condition lor.length == 6 is fulfilled and 5aTh46 string is returned from the top of the call stack. So, for the 5th call we have

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 is false since local lor is equal to 5aTh4. So, 5aTh46 returned by the 6th call is returned after the 5th call as well and so forth untill value 5aTh46 is finally returned as a result of co(lor)'s calls and added to the # string inside randColor. In the end we get #5aTh46.

PS. That's how I understand it. If you get the concepts of event loop and IIFE this explanation may sound simple :)




回答2:


Yes. It is an IIFE. The invocation starts with a ''. Then recursive calls are made which appends 1 character at a time from the array [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'] randomly. Six such characters are added( checked by (lor.length == 6)). The preceeding '#' is prepended to the 6 character to form a random color which is returned by the function randColor().




回答3:


(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 */)



回答4:


The code at first looks terrible. Let simplify it step by step.

//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() returns an expression which includes a function (in fact, IIFE).
Let put the result instead of function call. Meanwhile, parenthesis around the function can be omitted here because of + operator before.

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*/);
})

Still not easy? Let's take next step.

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); 
}

And final simplification. Use a loop instead of recursion.

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;
}

Leading # makes up correct HEX value for the color.




回答5:


"#" is a part of color code (#7b7b6e), the function returns a random string something like this "7b7b6e" and # is added infront of it



来源:https://stackoverflow.com/questions/46515833/can-someone-fluent-in-javascript-explain-to-me-whats-going-on-here-simply

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!