理解执行javascript的过程

时间:2016-09-19 01:16:46

标签: javascript jquery

我试图理解JavaScript的运行过程,但卡住了。第一个问题,在https://api.jquery.com/jQuery.each/中示例的第32行,为什么脚本会Will stop running after "three"

第二个问题,与jQuery: array[i].children() is not a function有关,我更新代码如下:

    var removeElements = function(text, selector) {
      var wrapped = $("<div>" + text + "</div>");
      wrapped.find(selector).remove();
      return wrapped.html();
    }

    var $fRef = $(".footnoteRef");
    for (var i = 0; i < $fRef.length; i++) {
      var sup = $fRef.children("sup")[i];
      //sup.setAttribute('fnID', $fRef[i].getAttribute("href").substring(1));
      var fnT = removeElements(document.getElementById($fRef[i].getAttribute("href").substring(1)).innerHTML, "a");
      sup.onmouseover = function(event) {
        var fnTip = document.getElementById('fnTip');
        if (fnTip) fnTip.parentNode.removeChild(fnTip);
        var pTip = document.createElement('div');
        //pTip.innerHTML = removeElements(document.getElementById(this.getAttribute('fnID')).innerHTML,"a");
        pTip.innerHTML = fnT;
        pTip.id = 'fnTip';
        pTip.style.position = 'absolute';
        pTip.style.left = (event.pageX - 180) + 'px';
        pTip.style.top = (event.pageY + 20) + 'px';
        pTip.style.width = '360px';
        pTip.style.textIndent = '2em';
        pTip.style.textAlign = 'left';
        pTip.style.backgroundColor = '#FFFFE0';
        pTip.style.border = '1px solid #636363';
        pTip.style.padding = '5px';
        pTip.style.fontSize = '12px';
        pTip.style.lineHeight = '1.8';
        pTip.style.borderRadius = '5px';
        document.body.appendChild(pTip);
      };

      sup.onmouseout = function(event) {
        var fnTip = document.getElementById('fnTip');
        if (fnTip) fnTip.parentNode.removeChild(fnTip);
      };
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Baryonyx was a theropod dinosaur of the early Cretaceous Period, about 130–125 million years ago<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>. An identifying specimen of the genus was discovered in 1983 in Surrey, England; fragmentary
  specimens<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a> were later discovered in other parts of the United Kingdom and Iberia. Meaning "heavy claw", Baryonyx refers to the animal's very large claw (31 cm or 12 in) on the first finger.
  The 1983 specimen<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> is one of the most complete theropod skeletons from the UK, and its discovery attracted media attention.</p>

<div class="footnotes">
  <hr>
  <ol>
    <li id="fn1">
      <p>Baryonyx caught and held its prey primarily with its strong forelimbs and large claws.<a href="#fnref1">↩</a>
      </p>
    </li>
    <li id="fn2">
      <p>The creature lived near bodies of water, in areas where other theropod, ornithopod, and sauropod dinosaurs have also been found. <a href="#fnref2">↩</a>
      </p>
    </li>
    <li id="fn3">
      <p>It had a long, low, bulbous snout and narrow, many-toothed jaws, which have been compared to gharial jaws.<a href="#fnref3">↩</a>
      </p>
    </li>
  </ol>
</div>

当鼠标位于脚注符号上标1和2上方时,工具提示显示脚注3的内容。为什么不显示自己的脚注?

我很困惑。

这不是JavaScript closure inside loops – simple practical example的简单副本,这里有两个问题:第一个问题与jQuery的$.each()循环的独特机制有关。第二个是关闭内部循环,但是,这里我们使用jQuery,我们还提供特定的解决方案(setAttribute来保存状态并在事件触发时检索)。

2 个答案:

答案 0 :(得分:1)

问题1

  

第一个问题,在https://api.jquery.com/jQuery.each/中的示例的第32行中,为什么脚本将在“三”之后停止运行?

因为each在您返回false时停止运行。这条线

return ( val !== "three" );

一旦迭代到达字符串false,将返回"three"(因为"three" !== "three"false

如果您阅读的文档略高于该代码示例,则说明:

  

我们可以通过使回调函数返回false来在特定迭代中中断$ .each()循环。返回非false与for循环中的continue语句相同;它将立即跳到下一次迭代。

问题2

  

当鼠标位于脚注符号上标1和2上方时,工具提示显示脚注3的内容。为什么不显示自己的脚注?

原因是JavaScript中常见的closure inside loops问题。

当您查看代码的这一部分时:

for (var i = 0; i < $fRef.length; i++) {
  // ...

  var fnT = // ... here you create a fnT for each i
  sup.onmouseover = function(event) {
    pTip.innerHTML = fnT; // this happens when the loop is finished, so its always the last fnT

  // ...

正在发生的事情是循环正在迭代并将内容存储在fnT中。然后,循环结束,最后一个fnT是第三个。一段时间后,你徘徊 在sup上方,它显示了它可以访问的fnT,这仍然是第三个。

解决这个问题的方法是将onmouseover侦听器提取到自己的函数中,然后将当前fnT传递给该函数。这样,每个侦听器都可以访问正确的fnT

for (var i = 0; i < $fRef.length; i++) {
  // ...

  var fnT = // ... here you create your fnT
  addListeners(sup, fnt);
}

function addListeners(sup, fnT) {
  sup.onmouseover = function(event) {
    // ...
    pTip.innerHTML = fnT; // here each listener gets a proper fnT because we pass it in on every loop iteration
    // ...
  }

  sup.onmouseout = function(event) {
    // ...
  }
}

示例运行示例的代码示例

var removeElements = function(text, selector) {
  var wrapped = $("<div>" + text + "</div>");
  wrapped.find(selector).remove();
  return wrapped.html();
}

var $fRef = $(".footnoteRef");
for (var i = 0; i < $fRef.length; i++) {
  var sup = $fRef.children("sup")[i];
  var fnT = removeElements(document.getElementById($fRef[i].getAttribute("href").substring(1)).innerHTML, "a");
  addListeners(sup, fnT);
}

function addListeners(sup, fnT) {
  sup.onmouseover = function(event) {
    var fnTip = document.getElementById('fnTip');
    if (fnTip) fnTip.parentNode.removeChild(fnTip);
    var pTip = document.createElement('div');
    pTip.innerHTML = fnT;
    pTip.id = 'fnTip';
    pTip.style.position = 'absolute';
    pTip.style.left = (event.pageX - 180) + 'px';
    pTip.style.top = (event.pageY + 20) + 'px';
    pTip.style.width = '360px';
    pTip.style.textIndent = '2em';
    pTip.style.textAlign = 'left';
    pTip.style.backgroundColor = '#FFFFE0';
    pTip.style.border = '1px solid #636363';
    pTip.style.padding = '5px';
    pTip.style.fontSize = '12px';
    pTip.style.lineHeight = '1.8';
    pTip.style.borderRadius = '5px';
    document.body.appendChild(pTip);
  };

  sup.onmouseout = function(event) {
    var fnTip = document.getElementById('fnTip');
    if (fnTip) fnTip.parentNode.removeChild(fnTip);
  };
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Baryonyx was a theropod dinosaur of the early Cretaceous Period, about 130–125 million years ago<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>. An identifying specimen of the genus was discovered in 1983 in Surrey, England; fragmentary
  specimens
  <a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a> were later discovered in other parts of the United Kingdom and Iberia. Meaning "heavy claw", Baryonyx refers to the animal's very large claw (31 cm or 12 in) on the first finger. The 1983
  specimen<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> is one of the most complete theropod skeletons from the UK, and its discovery attracted media attention.</p>

<div class="footnotes">
  <hr>
  <ol>
    <li id="fn1">
      <p>Baryonyx caught and held its prey primarily with its strong forelimbs and large claws.<a href="#fnref1">↩</a>
      </p>
    </li>
    <li id="fn2">
      <p>The creature lived near bodies of water, in areas where other theropod, ornithopod, and sauropod dinosaurs have also been found. <a href="#fnref2">↩</a>
      </p>
    </li>
    <li id="fn3">
      <p>It had a long, low, bulbous snout and narrow, many-toothed jaws, which have been compared to gharial jaws.<a href="#fnref3">↩</a>
      </p>
    </li>
  </ol>
</div>

答案 1 :(得分:0)

非常感谢nem035!

世界正在快速变化,我在20世纪90年代早期编写了C / C ++编码(1992-1995,之后,只使用简单的脚本编写软件包)。感谢您提供了许多有用的信息。

现在有了更好的理解,我删除了包含fnT

的行
for(let i=0; i<$fRef.length; i++) {
...
pTip.innerHTML = removeElements(document.getElementById($fRef[i].getAttribute("href").substring(1)).innerHTML,"a");

其中{1} var i=0let i=0循环中的for修改,以及(2)在触发onmouseover事件时直接提取脚注文本。