为什么更改等于 HTML 集合的变量会更改集合的原始值?

Why changing variable equal to a HTML collection changes the original values of the collection?

我看到了一种不同的行为,我无法真正理解为什么会发生这种情况。 本来,让一个变量等于另一个变量后,它只会将一个变量的值复制到另一个变量,但如果我在那之后改变一个变量的值,另一个变量不会受到影响,对吧?如:

let a = 3
let b = 5
b = a
//here the variable b, that was 5 will become the same as the variable a, becoming 3.
a = 10
//now, if I change the value in a to 10, b will still have the value of 3.

这很基础 JavaScript,我知道。但是知道这一点,我不明白为什么它在 HTMLcollection 方面有所不同。

情况如下:

const allLi = document.getElementsByTagName('li'); 
for (let xis of allLi) {
    xis.classList.toggle('highlight');
}

这里我得到一个HTMLcollection,赋值给变量allLi,然后我用for of循环修改它,从而改变了HTMLcollection中的原始值,即参考 li 元素的 class 值。

我的问题是:为什么在这种情况下,如果我通过循环更改变量,我就能够修改 HTML 集合中的原始值?为什么和上一个例子中的a声明一个新值而另一个变量保持不变不一样?

非常感谢。

Javascript 中的对象和数组是通过引用原始对象或数组来存储的。这会导致您观察到的行为。您存储在变量中的所有引用仍然指向同一个对象。

考虑以下因素:

let object1 = new Object // Reference to object instance 1
let object2 = new Object // Reference to object instance 2
let object3 = object1 // Reference to object instance 1

object1.prop1 = 'a'
object2.prop1 = 'b'
object3.prop1 = 'c'

object1.prop1 // 'c'
object2.prop1 // 'b'
object3.prop1 // 'c'

object1.prop1 保存值 'c' 因为 object1object3 引用对象的同一个实例(实例 1)所以 obect3.prop1 赋值更新 object1object3 变量引用的单个对象的值。

大多数 Web 浏览器控制台都会为您在控制台中引用的任何对象提供一个实例值,让您轻松了解两个变量是否引用同一个对象实例。

例如,Safari 控制台给出以下输出:

> let object1 = new Object // Reference to object instance 1
let object2 = new Object // Reference to object instance 2
let object3 = object1 // Reference to object instance 1
< undefined

> object1
< {} 

> object2
< {} 

> object3
< {} 

以 $ 开头的数字是对象实例编号。

您的第一个示例都使用标量值,并且标量值按值存储。也就是说,如果您创建一个新变量来存储标量值,并将另一个变量的值分配给它,那么您将获得该值,而不是对对象或变量的引用。然后该值独立于原始变量。