我已经玩了一段时间了。为什么在运行函数对val b进行排序时val_a会发生变化?我怎么能绕过这个?当我单独运行该功能时,它们可以工作,但是当我将它们一起运行时,某些地方出了问题。
var GLOBALS = {"items":[]};
var val_a;
var val_b;
GLOBALS.items=[
{"thing":"one","val_a":0.5,"val_b":0.2},
{"thing":"two","val_a":0.2,"val_b":0.3},
{"thing":"three","val_a":0.3,"val_b":0.1}];
val_a = GLOBALS.items.sort(function (a, b) {
a=parseFloat(a.val_a);
b=parseFloat(b.val_a);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
val_b = GLOBALS.items.sort(function (a, b) {
a=parseFloat(a.val_b);
b=parseFloat(b.val_b);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
console.log("val_a",val_a);
console.log("val_b",val_b);
答案 0 :(得分:5)
您看到所见的原因是val_a
和val_b
只包含对同一数组的引用,该引用也是从GLOBALS.items
引用的。 sort
更改所有这三个变量所指向的数组的状态。
变量包含值,而不是对象。处理对象(包括数组)时,变量中的值是对象的引用,它实际存在于内存的其他位置。将该引用视为一个数字,告诉JavaScript引擎对象在内存中的其他位置。 (更多信息如下。)
如果你想要三个独立的数组(原始items
,然后是按val_a
排序的副本,另一个按val_b
排序),你想要制作数组的浅表副本在排序之前,您可以使用slice
:
val_a = GLOBALS.items.slice().sort(...);
关于内存中其他地方的数组,这是一个更简单的例子:
var a = [42]; // A variable with a reference to an array, which is
// elsewhere in memory
这让我们记忆犹新:
+---------+ a<REF5512>--------->| (array) | +---------+ | 0: 42 | +---------+
(REF5512
只是完全弥补了引用是一个值。我们从未看到原始参考值。)
然后,如果我们这样做:
var b = a; // A copy of that same reference
这让我们记忆犹新:
a<REF5512>---+ | +---------+ +----->| (array) | | +---------+ b<REF5512>---+ | 0: 42 | +---------+
如果我们改变数组的状态(例如,通过对它进行排序),那么任何变量都可以看到变化,因为它们都指向同一个数组:
b[0] = 67;
给我们
a<REF5512>---+ | +---------+ +----->| (array) | | +---------+ b<REF5512>---+ | 0: 67 | State of the array changed +---------+
slice
创建一个 new 数组,其中包含旧数组中值的副本(只是值;数组中的对象不会被复制)。例如:
b = a.slice();
给我们:
+---------+ a<REF5512>--------->| (array) | +---------+ | 0: 67 | +---------+ +---------+ b<REF7341>--------->| (array) | +---------+ | 0: 67 | +---------+
请注意b
中的引用与a
中的引用不再相同。
附注:您的sort
回调可以更加简单:
val_a = GLOBALS.items.sort(function (a, b) {
return parseFloat(a.val_a) - parseFloat(b.val_a);
});
sort
回调只需要返回一个小于零的值(它不必具体为-1),大于零(它不必具体为1),或者等于零。