使条件函数更高效
Posted
技术标签:
【中文标题】使条件函数更高效【英文标题】: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
这样的字符串或条件。
我需要以更好的方式、更专业的方式重写此函数并按照描述的方式工作。
提前致谢。
【问题讨论】:
【参考方案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 的基础上,我建议您将plus
和minus
的常量分别定义为+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 == 0
和n % n == 0
开始,添加数组长度不会改变模结果,同时保持索引为正数。
(我将名称从MyArray
更改为tracks
和unaryChange
更改为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);
【讨论】:
以上是关于使条件函数更高效的主要内容,如果未能解决你的问题,请参考以下文章