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

Tee*_*sic 0 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);
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 6

你看到你所看到的是什么原因val_a,val_b只是包含对同一个数组的引用,也引用了它GLOBALS.items.sort更改所有这三个变量所指向的数组的状态.

变量包含值,而不是对象.处理对象(包括数组)时,变量中的值是对象的引用,实际上存在于内存的其他位置.将该引用视为一个数字,告诉JavaScript引擎对象在内存中的其他位置.(更多信息如下.)

如果你想要三个独立的数组(原始的items,然后是一个排序的副本val_a,另一个排序的val_b),你想在排序之前制作一个浅的数组副本,你可以这样做slice:

val_a = GLOBALS.items.slice().sort(...);
Run Code Online (Sandbox Code Playgroud)

关于数组在内存中的其他地方,这是一个更简单的例子:

var a = [42]; // A variable with a reference to an array, which is
              // elsewhere in memory
Run Code Online (Sandbox Code Playgroud)

这让我们记忆犹新:

                    +---------+
a<REF5512>--------->| (array) |
                    +---------+
                    | 0: 42   |
                    +---------+

(这REF5512完全是为了表明引用是一个值.我们永远不会看到原始引用值.)

如果我们这样做:

var b = a;    // A copy of that same reference
Run Code Online (Sandbox Code Playgroud)

这让我们记忆犹新:

a<REF5512>---+
             |      +---------+
             +----->| (array) |
             |      +---------+
b<REF5512>---+      | 0: 42   |
                    +---------+

如果我们改变数组的状态(例如,通过对它进行排序),那么任何变量都可以看到变化,因为它们都指向同一个数组:

b[0] = 67;
Run Code Online (Sandbox Code Playgroud)

给我们

a<REF5512>---+
             |      +---------+
             +----->| (array) |
             |      +---------+
b<REF5512>---+      | 0: 67   | State of the array changed
                    +---------+

slice创建一个数组,其中包含旧数组中值的副本(只是值; 数组中的对象不会被复制).例如:

b = a.slice();
Run Code Online (Sandbox Code Playgroud)

给我们:

                    +---------+
a<REF5512>--------->| (array) |
                    +---------+
                    | 0: 67   |
                    +---------+

                    +---------+
b<REF7341>--------->| (array) |
                    +---------+
                    | 0: 67   |
                    +---------+

注意引用如何b不再与in中相同a.


旁注:您的sort回调可以更简单:

val_a = GLOBALS.items.sort(function (a, b) {
    return parseFloat(a.val_a) - parseFloat(b.val_a);
});
Run Code Online (Sandbox Code Playgroud)

sort回调只是必须返回一个值小于零(它不必是具体-1),大于零(它不必是具体为1),或等于零.