【问题标题】:Why is my below code for IIFE only working once with the clickEvent为什么我下面的 LIFE 代码只在点击事件中工作一次
【发布时间】:2018-09-28 20:56:51
【问题描述】:

下面是我今天想到并创建的一个小项目的链接。我无法使用 IIFE 多次使按钮工作。我已经在没有 IIFE 的情况下解决了这个问题,但我的理解是最好将代码设为私有...任何建议将不胜感激。

https://codepen.io/kclute627/pen/dgPyxq

let randomColor = (function(){

// generate a random number 
let randNum= () => Math.floor(Math.random() * 10);
// invoke random number 6 times to create hexcolor
let randColor = parseInt([randNum(), randNum(), randNum(), randNum(), 
randNum(), randNum()].join(''))

const hexColor = (`#${randColor}`)

return hexColor;

})();

const makeColor = (function() {
let color1 = randomColor;
console.log(color1);
let setupEventListener = function(){ 

    document.querySelector('.final-button').addEventListener('click', 
function(){
        document.querySelector('.main-box').style.backgroundColor = color1;
    });
};

setupEventListener();

})();

【问题讨论】:

    标签: javascript iife


    【解决方案1】:

    randomColor 仅在文件首次加载时分配一次。 let color1 = randomColor; 只是获取 randomColor 的值,它不会再次运行您的 IIFE 以获得新颜色。

    randomColor 应该是一个函数(不是对 IIFE 的返回值的引用),如果您希望它再次运行并生成新颜色。如果你愿意的话,你可以用一个 IIFE 来定义整个事情的范围,如果你不希望它在全局范围内,可以将 randomColor 放在某种范围内。

    值得注意的是,您的点击处理程序在每次点击时都在运行,但颜色并没有改变,因为randomColor 没有改变。

    【讨论】:

    • 我明白你在说什么关于在单击按钮时再次运行 IIFE 的任何建议?
    • 好吧,你可以把它变成一个函数,而不是让它运行一个 IIFE。如果您希望函数作用域,您可以创建一个类并将其添加为方法,或者将其放入全局作用域的变量中(如 jQuery 或其他库如何公开自己)。
    【解决方案2】:

    在单击事件中,仅调用作为第二个参数的addEventListener 的函数。变量color1 在此函数之外分配,因此值将保持不变。

    【讨论】:

      【解决方案3】:

      只是对 randomColor 函数的扩展注释。

      我不喜欢在函数声明中使用函数表达式。赋值仍然会创建一个全局变量,不保存任何字符,并且引入了声明不存在的问题。

      在函数内部,还有另一个函数表达式被调用了 6 次,然后创建并连接了一个数组,最后使用了 parseInt,这会引入零星的错误(它会删除前导零所以该值不再有 6 位数字)并且考虑到您想要一个字符串结果是完全没有必要的。

      最后,结果值实际上是十进制的,因为它只包含从 0 到 9 的数字。

      使用循环可能不合时宜,但它们确实是基本的,至少应该在指出它们的地方加以考虑。例如:

      // Generate random 6 digit hex value where digits are 0 - 9
      function randomColor() {
        var color = '#';
        for (var i=0; i<6; i++) {
          color = color + Math.floor(Math.random() * 10);
        }
        return color;
      }
      
      console.log('Decimal color: ' + randomColor());

      如果要生成十六进制值(数字 0 到 f),请考虑:

      // Generate random 6 digit hex value
      // This uses parseInt to get hex value, but makes it a string
      // immediately so leading zeros are kept if they occur
      function randomHexColor() {
        var color = '#';
        for (var i = 0; i < 6; i++) {
          color = color + (Math.random() * 16 | 0).toString(16);
        }
        return color.toUpperCase();
      }
      
      console.log('Hexidecimal color: ' + randomHexColor());

      或者,如果您必须使用更新的功能,并创建更通用的功能,也许:

      // Generate hex value of length len
      function getRandomHex(len) {
        return new Array(len).fill(0).map(x=>(Math.random()*16|0).toString(16)).join('');
      }
      
      console.log('#' + getRandomHex(6).toUpperCase())

      这更短,但效率要低得多。如果 Array.prototype.fill 接受表达式而不是原始值,这可能是一个可行的选择,例如:

      var randomArray = new Array(6).fill((Math.random()*16|0).toString(16));
      

      对每个值都进行了评估,但它只评估了一次,并且对每个元素重复了该值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-13
        • 2015-01-05
        • 2017-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多