Javascript 反转HTML标记,理解分配

Javascript 反转HTML标记,理解分配,javascript,html,Javascript,Html,在下面的HTML <nav> <a href="home.html">home</a> <a href="about.html">about</a> <a href="more.html">more</a> <a href="contact.html">contact</a> </nav> 我认为这会起作用: for(j = 0; j < max; j

在下面的HTML

<nav>
  <a href="home.html">home</a>
  <a href="about.html">about</a>
  <a href="more.html">more</a>
  <a href="contact.html">contact</a>
</nav>
我认为这会起作用:

for(j = 0; j < max; j += 1) {
  n.children[j].innerHTML = arrReverse[j].innerHTML;
  n.children[j].href = arrReverse[j].href;
}
(j=0;j{ n、 子类[j].innerHTML=arrReverse[j].innerHTML; n、 children[j].href=arrReverse[j].href; } 但事实并非如此。输出为
contact more contact

有人能解释一下,为什么这不起作用


我认为这是因为您在这里存储引用(因为children[I]是object):

因此,您的
arrReverse
元素是对
n
children[i]
的引用,而不是对新对象的引用。这就是为什么在这里:

n.children[j].innerHTML = arrReverse[j].innerHTML;
n.children[j].href = arrReverse[j].href;
您将获得在上一个循环迭代中更改的值

正确的代码是:

var n = document.querySelector("nav");
var max = n.children.length;
var arrReverse = [];

for(i = (max - 1); i > -1; i -= 1) {
  arrReverse.push(clone(n.children[i]));  //here we store new objects, not references
}

for(j = 0; j < max; j += 1) {
  // console.log(arrReverse[j].innerHTML);
  n.children[j].innerHTML = arrReverse[j].innerHTML;
  n.children[j].href = arrReverse[j].href;
}

function clone(obj)
{ 
   var clone = {};
   clone.prototype = obj.prototype;
   for (property in obj) clone[property] = obj[property];
   return clone;
}
var n=document.querySelector(“nav”);
var max=n.children.length;
var arrReverse=[];
对于(i=(最大值-1);i>-1;i-=1){
arrReverse.push(clone(n.children[i]);//这里存储的是新对象,而不是引用
}
对于(j=0;j

您不需要调用循环中的
DOM
元素,它们在每次迭代中都会发生变化:

for (j = 0; j < max; j += 1) {
    n.children[j].innerHTML = arrReverse[j].innerHTML;
    n.children[j].href = arrReverse[j].href;
}
(j=0;j{ n、 子类[j].innerHTML=arrReverse[j].innerHTML; n、 children[j].href=arrReverse[j].href; } 最好保存它们的数据,将其反转,并将其显示给用户

var n = document.querySelector("nav");
var a = n.querySelectorAll("a"),
    max = a.length;
var arrReverse = [],
    menu = [],
    i, j, k = 0;

// save data
for (k = 0; k < max; k++) {
    menu[k] = {
        text: a[k].innerHTML,
        link: a[k].href
    }
}

// reverse data
for (i = (max - 1); i > -1; i -= 1) {
    arrReverse.push(menu[i]);
}

// print reversed data
for (j = 0; j < max; j += 1) {
    a[j].innerHTML = arrReverse[j].text;
    a[j].href = arrReverse[j].link;
}
var n=document.querySelector(“nav”);
变量a=n.querySelectorAll(“a”),
最大值=a.长度;
var arrReverse=[],
菜单=[],
i、 j,k=0;
//保存数据
对于(k=0;k-1;i-=1){
arrrerse.push(菜单[i]);
}
//打印反向数据
对于(j=0;j

menu=[]
存储数据,然后将其反转(在新数组中)。在最后一个循环中,您只需从中获取数据并设置在正确的位置


希望你正在寻找这个。

当你改变
n.孩子们也会改变

var n = document.querySelector("nav");
var max = n.children.length;
var arrReverse = [];

for(i = (max - 1); i > -1; i -= 1) {
  arrReverse.push([n.children[i].innerHTML,n.children[i].href]);
}

for(j = 0; j < max; j += 1) {
  // console.log(arrReverse[j].innerHTML);
  n.children[j].innerHTML = arrReverse[j][0];
  n.children[j].href = arrReverse[j][1];
}
var n=document.querySelector(“nav”);
var max=n.children.length;
var arrReverse=[];
对于(i=(最大值-1);i>-1;i-=1){
arrReverse.push([n.children[i].innerHTML,n.children[i].href]);
}
对于(j=0;j
arrReverse
数组中,您正在通过引用存储包含在中的元素,因此,原始
HTMLCollection
中的任何更改都将更改该数组中的元素。另一方面,您需要知道您正在使用该属性,它将返回一个live
HTMLCollection
。这意味着直接在DOM中所做的任何更改都将自动更新
HTMLCollection

因此,很容易理解发生了什么:

这是从
n.children
返回的
HTMLCollection
的表示形式:

0 => <a href="home.html">home</a>
1 => <a href="about.html">about</a>
2 => <a href="more.html">more</a>
3 => <a href="contact.html">contact</a>
运行时:

n.children[0].innerHTML = arrReverse[0].innerHTML;
n.children[0].href = arrReverse[0].href;

n.children[1].innerHTML = arrReverse[1].innerHTML;
n.children[1].href = arrReverse[1].href;
这将是两个对象的状态:

HTMLCollection:

0 => <a href="contact.html">contact</a>
1 => <a href="more.html">more</a>
2 => <a href="more.html">more</a>
3 => <a href="contact.html">contact</a>
0 => <a href="contact.html">contact</a> (reference of the HTMLCollection index 3)
1 => <a href="more.html">more</a> (reference of the HTMLCollection index 2)
2 => <a href="more.html">more</a> (reference of the HTMLCollection index 1)
3 => <a href="contact.html">contact</a> (reference of the HTMLCollection index 0)
因此,如果不继续循环,此时这两个对象都失去了对
about
home
的引用。结果将是
联系更多联系

为了方便地避免此问题,我们可以采用两种方法:

  • 使用非活动集合,如果 之所以使用,是因为它返回一个静态 (非现场)。因此,在本例中,如果更改DOM 直接而言,
    NodeList
    不会被更新,这意味着 不需要辅助阵列来存储数据,我们可以使用 就我们所知,原始集合中存储的数据是相同的 直接修改其中的元素
  • 可以使用直接修改DOM(而不修改
    节点列表中的元素),因为使用
    它直接在元素中更改
    DOM
    ,而不更改 原始元素(请阅读此属性文档中的下一个引号)
  • 此外,虽然文档中的元素将被替换,但设置了outerHTML属性的变量仍将保留对原始元素的引用

    您可以通过以下方法获得解决方案:

    var-anchors=document.querySelectorAll(“导航a”);
    anchors.forEach((a,i)=>a.outerHTML=anchors[anchors.length-i-1].outerHTML)
    
    
    
    它必须存储一个引用,但如果您存储旁注,解决方案是我找不到的:如果
    i
    j
    存在于更高的范围内,您可能希望在
    中为
    循环使用
    var i
    var j
    ,否则您将覆盖它们的值。(如果您在ES2015环境中工作,
    让我
    。@Liam:我知道如何调试!如果我知道的话,我不会问这个问题。有时需要一点提示来睁开眼睛。您的解决方案不正确。它不会分配
    hrefs
    。啊,是的,克隆会破坏对象引用基本上再次破坏对象引用,但不会克隆所有内容非常感谢!我把数组和对象弄混了,没有认出它。好的和清晰的解决方案!
    n.children[0].innerHTML = arrReverse[0].innerHTML;
    n.children[0].href = arrReverse[0].href;
    
    n.children[1].innerHTML = arrReverse[1].innerHTML;
    n.children[1].href = arrReverse[1].href;
    
    0 => <a href="contact.html">contact</a>
    1 => <a href="more.html">more</a>
    2 => <a href="more.html">more</a>
    3 => <a href="contact.html">contact</a>
    
    0 => <a href="contact.html">contact</a> (reference of the HTMLCollection index 3)
    1 => <a href="more.html">more</a> (reference of the HTMLCollection index 2)
    2 => <a href="more.html">more</a> (reference of the HTMLCollection index 1)
    3 => <a href="contact.html">contact</a> (reference of the HTMLCollection index 0)