调用两次时,Array.sort无法正常工作?

时间:2016-07-02 10:33:54

标签: javascript arrays sorting

我已经玩了一段时间了。为什么在运行函数对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);

1 个答案:

答案 0 :(得分:5)

您看到所见的原因是val_aval_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),或者等于零。