【问题标题】:Making a conditional function more efficient使条件函数更高效
【发布时间】:2019-10-10 14:22:12
【问题描述】:

我想创建一个根据给定参数修改变量的函数。

该函数检查一个变量和该字符串中的数字。然后通过参数,我指定将数字增加或减少 1 (++1)。

还有一个数组,如果数字等于数组的长度,则变为1,如果数字小于1,则等于数组的大小。这是为了确保字符串的数量不小于 1 或大于数组的长度。

带有数字的字符串是Music1。所以这个圈子就像: ...., Music1, Music2, Music3, Music4, Music1, Music2, Music3, ....

var MyArray = ["Music1", "Music2", "Music3", "Music4"];
var currentMusic = "Music1";

$(".increase").on('click tap', nextMusic);
$(".decrease").on('click tap', previousMusic);

function nextMusic() {
  unaryChange('plus')
}

function previousMusic() {
  unaryChange('minus')
}

function unaryChange(operation) {
  if (currentMusic === "Music4") {
    currentMusic = "Music1"
  } else if (currentMusic === "Music0") {
    currentMusic = "Music4"
  }
  if (operation === "plus") {
    currentMusic = currentMusic.replace(/\d+$/, function(n) {
      return ++n
    });
  } else {
    currentMusic = currentMusic.replace(/\d+$/, function(n) {
      return --n
    });
  }

  console.log(currentMusic);
  $(".text").text(currentMusic);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button class="increase">increase</button>
<button class="decrease">decrease</button>
<p class="text">value</p>

上述方法几乎可以完成工作,但是我正在寻找一种更简单、更专业的解决方案。它看起来效率不高。例如,必须有更好的方法来指定参数operation,而不是像plus 这样的字符串或条件。

我需要以更好的方式、更专业的方式重写此函数并按照描述的方式工作。

提前致谢。

【问题讨论】:

    标签: javascript jquery html arrays function


    【解决方案1】:

    您可以为plus 传递布尔值,使用箭头函数和三元运算符:

    var MyArray = ["Music1", "Music2", "Music3", "Music4"];
    var currentMusic = "Music1";
    
    $(".increase").on('click tap', nextMusic);
    $(".decrease").on('click tap', previousMusic);
    
    function nextMusic() {
      unaryChange(true)
    }
    
    function previousMusic() {
      unaryChange(false)
    }
    
    function unaryChange(plus) {
      currentMusic = currentMusic == "Music4" ? "Music1" : (currentMusic == "Music0" ? "Music4" : currentMusic);
      currentMusic = currentMusic.replace(/\d+$/, n => plus ? ++n : --n);
      console.log(currentMusic);
      $(".text").text(currentMusic);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <button class="increase">increase</button>
    <button class="decrease">decrease</button>
    <p class="text">value</p>

    【讨论】:

      【解决方案2】:

      Joe's answer 的基础上,我建议您将plusminus 的常量分别定义为+1-1,以简化递增/递减逻辑,同时使用the modulus operator 来处理数组换行-周围:

      const PLUS = 1;
      const MINUS = -1;
      
      function unaryChange(operation) {
        var currentIndex = MyArray.findIndex(function(item) {
          return item === currentMusic;
        });
      
        // If it's invoked as unaryChange(PLUS) or unaryChange(MINUS)
        // we don't need any conditional logic to handle the increment,
        // and with the % operator we don't need additional bounds overflow
        // logic. (This latter bit is complicated somewhat by the need to
        // handle a minus step from index 0.)
        const {length} = MyArray;
        const newIndex = ((currentIndex + operation) % length + length) % length;
      
        currentMusic = MyArray[newIndex]
        $(".text").text(currentMusic);
      }
      

      % 运算符返回除法的余数,当与数组索引一起用于数组长度时,它可以方便地循环回 0:

      const array = ['first', 'second', 'third'];
      
      for (let i = 0; i < 20; i++) {
        console.log(array[i % array.length]);
      }

      【讨论】:

      • 好主意,但如果当前索引为 0 并且在这种情况下将减号发送到函数 -1 % 4 为 -1,它将不起作用
      • 已更新以处理负索引。
      【解决方案3】:

      最好使用数组索引而不是值

      function unaryChange(operation) {
        var currentIndex = MyArray.findIndex(function(item) {
          return item === currentMusic;
        });
      
        if(operation === 'plus') {
          newIndex = currentIndex < MyArray.length - 1 && currentIndex + 1 || 0;
        } else {
          newIndex = currentIndex > 0 ? currentIndex -1 : MyArray.length -1;
        }
      
        currentMusic = MyArray[newIndex]
        $(".text").text(currentMusic);
      }
      

      在这种情况下,无论数组大小如何,它都可以工作。

      一个工作示例https://jsbin.com/rahomorupa/4/edit?html,js,console,output

      【讨论】:

        【解决方案4】:

        我认为这是一个好的开始。访问数组的索引与值相比感觉要干净得多。使用三元组也可以将大量逻辑清理到一行中。

        var MyArray = ["Music1", "Music2", "Music3", "Music4"];
        var currentMusic = 0;
        
        $(".increase").on('click tap', unaryChange);
        $(".decrease").on('click tap', unaryChange);
        
        function unaryChange() {
          if (event.target.className === "increase") {
            currentMusic = (currentMusic < 3 ? currentMusic + 1 : 0)
          } else {
            currentMusic = (currentMusic > 0 ? currentMusic -= 1 : 3) 
          }
          console.log(MyArray[currentMusic]);
          $(".text").text(MyArray[currentMusic]);
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        
        <button class="increase">increase</button>
        <button class="decrease">decrease</button>
        <p class="text">value</p>

        【讨论】:

          【解决方案5】:

          这就是我的做法。由于 Music 这个词似乎只是一个用于指定特定单元的前缀,所以我不会一遍又一遍地将它存储在一个数组中。 至于 jQuery?是的,不。

          "use strict";
          function byId(id){return document.getElementById(id)}
          
          window.addEventListener('load', onLoaded, false);
          
          function onLoaded(evt)
          {
          	let prefix = 'Music';
          	let count = 4, index=0;
          	byId('increase').addEventListener('click', function(evt){index++; index %= count; update();}, false);
          	byId('decrease').addEventListener('click', function(evt){index--; if (index<0) index=count-1; update();}, false);
          	
          	function update()
          	{
          		byId('status').textContent = `${prefix}${index+1}`;
          	}
          }
          <span id='status'>Music1</span><br>
          <button id='increase'>+</button><button id='decrease'>-</button>

          【讨论】:

            【解决方案6】:

            由于您拥有一系列音乐,因此最好使用它。无需从文本中操作,只需将数组索引更新为下一个值并传递给函数,让它直接获取歌曲名称即可。

            由于我们想要介于 0 和数组长度的边界之间,所以我们可以这样做:

            • 获取下一首歌曲:(currentTrackIndex + 1) % tracks.length。这将获得下一个索引值并对它应用模数,因此如果它超过数组长度,它将返回。
            • 获取上一首歌曲:(currentTrackIndex - 1 + tracks.length) % tracks.length。这与获取下一首歌曲几乎相同,除了索引已经为零的情况。如果您对负数应用模数,您将得到一个负数结果并且会弄乱您的数组索引。因此,让我们添加数组长度,而不是使用条件子句(“if (currentTrackIndex === 0 ...)”)。为什么?因为从0 % n == 0n % n == 0 开始,添加数组长度不会改变模结果,同时保持索引为正数。

            (我将名称从MyArray 更改为tracksunaryChange 更改为changeTrack,以使其含义更清晰)

            var tracks = ["Music1", "Music2", "Music3", "Music4"];
            
            var currentTrackIndex = 0;
            
            $(".increase").on('click tap', nextMusic);
            $(".decrease").on('click tap', previousMusic);
            
            function nextMusic() {
              //It will move to the next track. If it's over the array length, it will reset to 0
              changeTrack((currentTrackIndex + 1) % tracks.length)
            }
            
            function previousMusic() {
              //It will move to the previous song. If it's below zero, it will reset to the last track index
              changeTrack((currentTrackIndex + tracks.length - 1) % tracks.length)
            }
            
            function changeTrack(newTrackIndex) {
              currentTrackIndex = newTrackIndex;
              var currentTrack = tracks[currentTrackIndex];
              console.log(currentTrackIndex);
              $(".text").text(currentTrack);
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-11-12
              • 2010-09-21
              • 1970-01-01
              • 2022-01-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多