如何在JavaScript中最小化函数内的重复代码

时间:2019-06-30 15:47:46

标签: javascript

我在轮播接口的每个函数中都有以下三个行代码:dots[(i+len-1)%len].className = dots[(i+len-1)%len].className.replace(" active", "")的作用是在点元素的每次迭代中都删除上一个“ active”类。如果我没有在每个函数上添加此代码,则“活动”类在点元素的每次迭代中传播不止一个,那么每次迭代都是这样的:<span class="dot active active active active" onclick="dotSlide(1)"></span>会导致幻灯片中的错误旋转木马或当我按下“下一个”或“上一个”按钮时,活动点未通过相应的索引与图像对齐。我的问题是,是否有办法减少每个函数的代码?

var slideIndex = 0;
loop();
var slides, dots;

function loop() {
  slides = document.getElementsByClassName("slides");
  dots = document.getElementsByClassName("dot");
  for (var i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  slideIndex++;
  var len = dots.length;
  if (slideIndex > slides.length) {
    slideIndex = 1
  }
  for (var i = 0; i < dots.length; i++) {
    dots[i].className = dots[i].className.replace(" active", "");
    dots[(i + len - 1) % len].className = dots[(i + len - 1) % len].className.replace(" active", "")

    dots[(i + len - 2) % len].className = dots[(i + len - 2) % len].className.replace(" active", "");
    dots[(i + len - 3) % len].className = dots[(i + len - 3) % len].className.replace(" active", "")
  }
  slides[slideIndex - 1].style.display = "block";
  dots[slideIndex - 1].className += " active";
  setTimeout(loop, 6000); // Change image every 6 seconds
}

function plusSlides(position) {
  var len = dots.length;
  slideIndex += position;
  if (slideIndex > slides.length) {
    slideIndex = 1
  } else if (slideIndex < 1) {
    slideIndex = slides.length
  }
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  for (i = 0; i < dots.length; i++) {
    dots[i].className = dots[i].className.replace(" active", "");
    dots[(i + len - 1) % len].className = dots[(i + len - 1) % len].className.replace(" active", "");
    dots[(i + len - 2) % len].className = dots[(i + len - 2) % len].className.replace(" active", "")
    dots[(i + len - 3) % len].className = dots[(i + len - 3) % len].className.replace(" active", "")
    slides[slideIndex - 1].style.display = "block";
    dots[slideIndex - 1].className += " active";
  }
}

function dotSlide(index) {
  if (index > slides.length) {
    index = 1
  } else if (index < 1) {
    index = slides.length
  }
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  var len = dots.length;
  for (i = 0; i < dots.length; i++) {
    dots[i].className = dots[i].className.replace(" active", "");
    dots[(i + len - 1) % len].className = dots[(i + len - 1) % len].className.replace(" active", "");
    dots[(i + len - 2) % len].className = dots[(i + len - 2) % len].className.replace(" active", "")
    dots[(i + len - 3) % len].className = dots[(i + len - 3) % len].className.replace(" active", "")
    slides[index - 1].style.display = "block";
    dots[index - 1].className += " active";
  }
}
<div id="slide">
  <div class="slides-container" style="text-align:center">
    <div class="slides fadeOut"> <img src="images/pine_forest.jpg"> </div>
    <div class="slides fadeOut"> <img src="images/best-forest.jpg"> </div>
    <div class="slides fadeOut"> <img src="images/EarthBeauty221.jpg"> </div>
    <div class="slides fadeOut"> <img src="images/setwalls.ru-79192.jpg"> </div>
    <a class="prev" onclick="plusSlides(-1)">&#10094;</a>
    <a class="next" onclick="plusSlides(1)">&#10095;</a>
  </div>
</div>
<div class="dots" style="text-align:center">
  <span class="dot" onclick="dotSlide(1)"></span>
  <span class="dot" onclick="dotSlide(2)"></span>
  <span class="dot" onclick="dotSlide(3)"></span>
  <span class="dot" onclick="dotSlide(4)"></span>
</div>

1 个答案:

答案 0 :(得分:1)

在这种情况下,通常的解决方案适用于实用程序功能和循环。一,实用功能:

// NOTE: We'll come back to this function, it has potential issues
function removeSubsequentClass(element, cls) {
  element.className = element.className.replace(" " + cls, "");
}

那么您至少要拥有:

removeSubsequentClass(dots[(i+len-1)%len], "active");
removeSubsequentClass(dots[(i+len-2)%len], "active");
removeSubsequentClass(dots[(i+len-3)%len], "active");

它还具有封装该功能的优势,此功能稍后会有用。

这已经是一个改进,但是我们也可以对此进行循环:

for (let n = 1; n <= 3; ++n) {
    removeSubsequentClass(dots[(i+len-n)%len], "active");
}

关于removeSubsequentClass:非常脆弱。它假定:

  • 该课程将不是 first
  • 该类将不是另一个类的子字符串(考虑:class="foo active-nifty-thing",它将变成class="foo-nifty-thing"-哎呀!)

在任何现代浏览器上,您都可以使用classList(可以填充)。我们还可以从名称中删除资格:

// NOTE: We'll come back to this function, it has potential issues
function removeClass(element, cls) {
  element.classList.remove(cls);
}

如果您需要支持不带classList的过时浏览器并且不想执行polyfill,那么:

function removeClass(element, cls) {
  element.className = (" " + element.className + " ")
    .replace(" " + cls + " ", "")
    .replace(/(?:^ +)|(?: +$)/g, "");
}

如果您想使用一个replace,并保证您的类将不包含任何用正则表达式特殊对待的字符,则:

function removeClass(element, cls) {
  element.className = (" " + element.className + " ")
    .replace(new RegExp("(?:^ +)|(?: +$)|(?: " + cls + " )", "g"), "");
}

或使用regular expression escape function,如果上述名称可能对以上名称不安全:

function removeClass(element, cls) {
  element.className = (" " + element.className + " ")
    .replace(new RegExp("(?:^ +)|(?: +$)|(?: " + theEscapeFunctionGoesHere(cls) + " )", "g"), "");
}