为什么 javascript "for loop" 对不同类型的对象有不同的行为

Why javascript "for loop" has different behaviours for different type of objects

我意识到 JavaScript 没有指针,但是我注意到循环遍历包含对象的数组时的这种 "pointer" 行为,但没有注意到数组包含数字(例如)时的类似行为。

var ARR_num = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0, len = ARR_num.length; i < len; i++) {
  var item = ARR_num[i];
  item++;
}
console.log(ARR_num);
//Outputs [0,1,2,3,4,5,6,7,8,9]

现在有了包含对象的数组

var ARR_obj = [{}, {}, {}];
for (var i = 0, len = ARR_obj.length; i < len; i++) {
  var item = ARR_obj[i];
  item.pointer = true;
}
console.log(ARR_obj);
//Outputs [{pointer: true}, {pointer: true}, {pointer: true}]

为什么会有这两种截然不同的行为?

Why these two distinct behaviours?

因为你有两个不同的操作。在后者中,你正在改变对象的状态

item.pointer = true;

item 一直指向同一个对象。仅更改了对象的内部结构。

但是这里

item++; # equivalent to item = item + 1

重新分配 项目。运算后会指向另一个整数。如果你在对象循环中做类似的操作

item = { pointer: true }

那么你原来的数组元素不会受到影响,你也不会观察到任何"pointer semantics"。

是的,它也与作为 primitive/immediate 值的整数有关。

{} 是对象文字语法,它在数组中创建(在您的情况下)新对象。当遍历它并使用 ARR_obj[i] 时,您将获得引用的对象,然后对其进行操作。

或者换句话说(更一般的):

基元(undefined、null、boolean、string 和 number)按值传递,而对象按引用传递(或准确地说是引用的副本)。

正如我们所知,所有值(不是原始值)都是对象指针。 所以 item 在用例 2 中是一个对象指针,而在用例 1 中它是整数。

在用例 2 中,它指的是所有迭代的值 "true"。所以根据编写的代码给出当前结果。

一般JavaScript不支持引用传参,所以使用Javascript中的Objects,我们可以传引用。

为什么会有这两种截然不同的行为?

当您将 对象 分配给另一个变量时,新变量指向相同的对象,因此当您更改新变量的属性时,对象会发生变化 示例:

var a= {name: "some"};
var b = a;
b.name = "newName";
console.log(a.name);// "newName"

当你将一个原始类型分配给另一个变量时,它只是一个新变量并且没有引用旧变量,因此更改新变量不会影响旧变量。 示例:

var a = "some";
var b = a;
b = "newName";
console.log(a);//"some"

希望这会有所帮助!!