首页 > 解决方案 > JavaScript 函数,与函数参数相关的错误

问题描述

我很抱歉这个问题很难表达,标题可能会产生误导。这个问题基本上与将参数传递给 JavaScript 中的函数有关。

下面的这些代码是一个允许元素水平移动的函数。它用于滑块。我的问题与我评论的两行特别相关。

我在一个名为common.js的单独 .js 文件中编写了如下函数,它工作正常:

(注意我评论的两行)

function animateX(element, target, stepWidth) {     // the stepWidth parameter
    clearInterval(element.timerId);
    element.timerId = setInterval(function () {
        var current = element.offsetLeft;
        var step = stepWidth;                       // This line
        step = current < target ? step : -step;
        current += step;
        if (Math.abs(target - current) > Math.abs(step)) {
            element.style.left = current + "px";
        } else {
            clearInterval(element.timerId);
            element.style.left = target + "px";
        }
    }, 10);
}

但是,如果我这样写,就会出现一个bug:

过渡消失了,当我点击箭头时,图片立即移动到目标,而不是滑动到目标。

function animateX(element, target, step) {     // the parameter uses the same name as the local variable
    clearInterval(element.timerId);
    element.timerId = setInterval(function () {
        var current = element.offsetLeft;
        var step = step;                       // This line: stepWidth -> step
        step = current < target ? step : -step;
        current += step;
        if (Math.abs(target - current) > Math.abs(step)) {
            element.style.left = current + "px";
        } else {
            clearInterval(element.timerId);
            element.style.left = target + "px";
        }
    }, 10);
}  

而且,如果我这样写,它会变得更糟:

图片不会按计划移动,它会移动一点然后颤抖。

function animateX(element, target, step) {          // This line
    clearInterval(element.timerId);
    element.timerId = setInterval(function () {
        var current = element.offsetLeft;
       // Now I understand why this one is wrong.
        // I changed it to step = current < target ? Math.abs(step) : -Math.abs(step);
        // Problem solved.
        step = current < target ? step : -step;
        current += step;
        if (Math.abs(target - current) > Math.abs(step)) {
            element.style.left = current + "px";
        } else {
            clearInterval(element.timerId);
            element.style.left = target + "px";
        }
    }, 10);
}

我完全认为这三种方式是一样的,但它们给了我完全不同的结果。

我还认为第三种方式更好,因为它的行数更少。但是,它不起作用。

有人可以向我解释一下区别吗?我真的很感激!

下面是html代码,有时间可以复制试试。这个 html 文件和 js 函数就是它工作所需要的。不用图片就能看出区别。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0
        }

        ul {
            list-style: none
        }

        img {
            vertical-align: top;
        }

        .box {
            width: 960px;
            height: 540px;
            margin: 100px auto;
            padding: 5px;
            border: 1px solid #ccc;
        }

        .inner {
            width: 960px;
            height: 540px;
            background-color: pink;
            overflow: hidden;
            position: relative;
        }

        .inner ul {
            width: 1000%;
            position: absolute;
            top: 0;
            left: 0;
        }

        .inner li {
            float: left;
        }

        #imgs li a {
            width: 960px;
            height: 540px;
            display: block;
        }

        #focusD {
            display: none;
        }

        #focusD span {
            position: absolute; /* inner是relative */
            width: 40px;
            height: 40px;
            left: 5px;
            top: 50%;
            margin-top: -20px;
            background: #000;
            font-family: arial, sans-serif;
            cursor: pointer;
            line-height: 40px;
            text-align: center;
            font-weight: bold;
            font-size: 30px;
            color: #fff;
            opacity: 0.3;
            border: 1px solid #fff;
        }

        #focusD #right {
            right: 5px;
            left: auto;
        }

    </style>
</head>
<body>
<div class="box" id="box">
    <div class="inner">
        <ul id="imgs">
            <li><a href="#"><img src="images/d1.jpg" alt="d1"/></a></li>
            <li><a href="#"><img src="images/d2.jpg" alt="d2"/></a></li>
            <li><a href="#"><img src="images/d3.jpg" alt="d3"/></a></li>
            <li><a href="#"><img src="images/d4.jpg" alt="d4"/></a></li>
            <li><a href="#"><img src="images/d5.jpg" alt="d5"/></a></li>
        </ul>
        <div id="focusD">
            <span id="left">&lt;</span>
            <span id="right">&gt;</span>
        </div>
    </div>
</div>

<script type="text/javascript" src="common.js"></script>
<script type="text/javascript">
    // getElementByID
    function my$(id) {
        return document.getElementById(id);
    }
</script>
<script type="text/javascript">
    var box = my$("box");
    // get slider frame
    var inner = box.children[0];
    // get frame width
    var imgWidth = inner.offsetWidth;
    // get ul
    var ulObj = inner.children[0];
    // get div containing arrows
    var focusD = my$("focusD");

    // show / hide arrows
    box.onmouseover = function () {
        focusD.style.display = "block";
    };
    box.onmouseout = function () {
        focusD.style.display = "none";
    };

    var index = 0;
    // click left arrow
    my$("left").onclick = function () {
        if (index > 0) {
            index--;
            animateX(ulObj, -index * imgWidth, 20);
        }
    };
    // click right arrow
    my$("right").onclick = function () {
        if (index < ulObj.children.length - 1) {
            index++;
            animateX(ulObj, -index * imgWidth, 20);
        }
    };

</script>
</body>
</html>

标签: javascriptfunctionparametersslider

解决方案


在函数的第二次迭代中,您创建了一个名为“step”的变量,它与函数参数之一同名。在第三次迭代中,您不会创建函数工作所需的“stepWidth”副本。尝试创建一个具有不同名称的变量来存储您的“步骤”副本。

function animateX(element, target, step) {         
clearInterval(element.timerId);
element.timerId = setInterval(function () {
    var current = element.offsetLeft;
    var stepWidth = step;                          
    stepWidth = current < target ? stepWidth : -stepWidth;
    current += stepWidth;
    if (Math.abs(target - current) > Math.abs(stepWidth)) {
        element.style.left = current + "px";
    } else {
        clearInterval(element.timerId);
        element.style.left = target + "px";
    }
}, 10);

}


推荐阅读