JavaScript:排序对象

4
function Player() {
  var score;

  this.getScore = function() { return score; }
  this.setScore = function(sc) { score = sc; }
}

function compare(playerA, playerB) {
  return playerA.getScore() - playerB.getScore();
}

var players = [];

players['player1'] = new Player();
players['player2'] = new Player();

Array(players).sort(compare);

我有类似于上面的代码。当我用调试器逐步执行代码时,比较函数从未被调用,数组也没有被排序。我不确定我的代码哪里出了问题?


它“相似”并不意味着它等同。这个代码片段可能没有问题,但是差异可能会导致问题。 - xtofl
只有在分数值为整数的情况下才有效!您还可以在比较方法中进行字符串比较并返回-1、0或1。 - pramodc84
4个回答

12

由于您已指定数组内变量所属的键,因此它并未进行排序。排序仅会移动整数值键上的对象。如果您按以下方式创建数组,则应该可以看到排序效果:

var players = [new Player(), new Player()];

尽管如此,当然,它不会非常有效,因为您既没有可排序的分数也没有识别它们的方法。这样做:

function Player(name, score) {
  this.getName = function() { return name; }
  this.getScore = function() { return score; }
  this.setScore = function(sc) { score = sc; }
}

function comparePlayers(playerA, playerB) {
  return playerA.getScore() - playerB.getScore();
}

var playerA = new Player('Paul', 10);
var playerB = new Player('Lucas', 5);
var playerC = new Player('William', 7);

var players = [playerA, playerB, playerC];

for (var i = 0; i < players.length; i++)
    alert(players[i].getName() + ' - ' + players[i].getScore());

players.sort(comparePlayers);

for (var i = 0; i < players.length; i++)
    alert(players[i].getName() + ' - ' + players[i].getScore());

希望这能有所帮助。


那么关联数组无法进行排序吗? - tom
3
转译:将它们变成关联数组没有意义,因为你已经自己对它们进行了排序。你想要实现什么额外的功能,让你觉得需要使用关联数组呢? - icio

2
主要问题在于这一行代码:

Array(players).sort(compare);

Array(something) 会生成一个以 something 为元素的数组。请注意,compare 是用来排序的函数。
console.log(Array(players)); //[[player1, player2]]

使用数字索引数组代替像players['player1']这样的对象数组。

运行以下代码(如果没有Firebug,请将console.log替换为alert)。

function Player() {
  var score;
  //return this.score - else it returns undefined
  this.getScore = function() { return this.score; } 
  this.setScore = function(sc) { this.score = sc; }
}

function compare(playerA, playerB) {
  console.log("called " + playerA.getScore() + " " + playerB.score);
  //compare method should return 0 if equal, 1 if a > b and -1 if a < b
  return (playerA.getScore() == playerB.getScore()) ? 0 
     : ((playerA.getScore() > playerB.getScore()) ? 1 : -1);
}

var players = [];

players[0] = new Player();
players[1] = new Player();
players[2] = new Player();
players[3] = new Player();
players[0].setScore(9);
players[1].score = 14;
players[2].score = 11;
players[3].score = 10;
players.sort(compare);
console.log(players);//prints sorted array

0
可能是因为您的数组中没有任何“数组值” - 文本索引不被视为数组值,而是被视为对象属性(在JavaScript中,数组是“伪装成对象”的)。您可以向任何对象添加任意数量的属性,但是像sort这样的数组特定方法只接受“真正的”数组成员作为它们的参数(即仅具有数字索引的成员)。
var arr = new Array()
arr[0] = 1
arr[1] = 2
arr["textual_index"] = 3
alert(arr.length);

最后一行的警告是“2”而不是“3”,因为只有两个具有数字索引的值。


如果它是 arr[textual_index],不带引号,那会是文本索引还是"数组值"? - tom
"不带引号的返回翻译文本:textual_index将被视为名为textual_index的变量,并且它的值在[和]之间传递,因此,如果变量textual_value具有数字值,则它将被视为数组成员,否则作为对象的属性。" - Andris

0

你也可以像下面这样使用:

var a = [];
a.push(obj1);
a.push(obj2);
a.sort(compare);

所以你可以使用 push 方法而不是整数索引


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接