高分榜

高分榜

学习练习

简介

说明

除了number和string这类原始数据类型之外,JavaScript 中还有一种重要的数据类型,叫做object。 对象是键值对的集合。 因此,它们的用法与其他语言中常说的映射或字典相同。

在其他语言中,映射里的所有值通常必须是同一种数据类型。 在 JavaScript 中,只有键的类型受到限制:它必须是string。 同一个对象里的值可以有不同的类型。 它们可以是数字这样的原始类型,也可以是数组、其他对象,甚至函数。 这让对象的用途非常广泛,因此它们也是 JavaScript 中面向对象编程(OOP)的关键实体。

接下来,我们将重点讨论作为集合或映射的对象。 对象的其他用法会在其他概念中介绍,参见类等。

创建对象

使用大括号可以创建对象。 你还可以直接写入一些条目。 为此,先写出键,再写一个冒号,然后是值。

const emptyObject = {};

const obj = {
  favoriteNumber: 42,
  greeting: 'Hello World',
  useGreeting: true,
  address: {
    street: 'Trincomalee Highway',
    city: 'Batticaloa',
  },
  fruits: ['melon', 'papaya'],
  addNumbers: function (a, b) {
    return a + b;
  },
};

在 JavaScript 中,最后一项后面的尾随逗号是可选的。

你可能会奇怪,既然键本应是字符串,为什么不用引号括起来呢。 这是一种简写形式。 如果键符合 JavaScript 的标识符命名规则,就可以省略引号。 如果键名中包含特殊字符,就需要使用常规的字符串写法。

const obj = {
  '1keyStartsWithNumber': '...',
  'key/with/slashes': '...',
  'key-with-dashes': '...',
  'key with spaces': '...',
  '#&()[]{}èä樹keyWithSpecialChars': '...',
};

获取值

有两种方式可以获取指定键对应的值:点记法和方括号记法。

const obj = { greeting: 'hello world' };

obj.greeting;
// => hello world

obj['greeting'];
// => hello world

// Bracket notation also works with variables.
const key = 'greeting';
obj[key];
// => hello world

用点记法作为简写,和省略引号有相同的限制。 只有当键符合标识符的命名规则时,它才有效。

添加或修改值

可以使用赋值运算符=来添加或修改值。 同样,点记法和方括号记法都可以用。

const obj = { greeting: 'hello world' };

obj.greeting = 'Hi there!';
obj['greeting'] = 'Welcome.';

obj.newKey1 = 'new value 1';
obj['new key 2'] = 'new value 2';

const key = 'new key 3';
obj[key] = 'new value 3';

删除条目

可以使用delete关键字从对象中删除一个键值对。

const obj = {
  key1: 'value1',
  key2: 'value2',
};

delete obj.key1;
delete obj['key2'];

检查键是否存在

可以使用hasOwnProperty方法检查对象中是否存在某个键。

const obj = { greeting: 'hello world' };

obj.hasOwnProperty('greeting');
// => true

obj.hasOwnProperty('age');
// => false

遍历对象

有一种特殊的for...in循环,可以遍历对象的所有键。

const obj = {
  name: 'Ali',
  age: 65,
};

for (let key in obj) {
  console.log(key, obj[key]);
}
// name Ali
// age 65

为了避免难以察觉的错误,你应该始终假定for...in循环会以任意顺序访问键。 另外要注意,for...in在迭代过程中会包含继承的键。

说明

在这个练习中,你将实现一种记录本地街机厅最热门游戏高分的方式。

你需要实现 5 个函数,它们大多与操作一个保存高分的对象有关。

1. 创建新的高分榜

创建一个createScoreBoard函数,它创建的对象将作为高分榜。 这个对象的键是玩家的名字,值是他们的分数。 出于测试目的,你需要直接在对象里包含一条记录。 这条初始记录应该以The Best Ever作为玩家名,以1000000作为分数。

createScoreBoard();
// returns an object with one initial entry

2. 向高分榜添加玩家

要向高分榜添加玩家,请定义addPlayer函数。 它接受 3 个形参:

  • 第一个形参是一个已有的高分榜对象。
  • 第二个形参是玩家的名字,类型为字符串。
  • 第三个形参是分数,类型为数字。

添加新玩家后,该函数返回传入的那个高分榜对象。

addPlayer({ 'Dave Thomas': 0 }, 'José Valim', 486373);
// => {'Dave Thomas': 0, 'José Valim': 486373}

3. 从高分榜中移除玩家

如果玩家违反街机厅的规定,他们会被手动从高分榜中移除。 定义removePlayer函数,它接受 2 个形参:

  • 第一个形参是一个已有的高分榜对象。
  • 第二个形参是玩家的名字,类型为字符串。

这个函数应该把指定玩家的记录从榜单中移除,然后返回榜单。 如果该玩家本来就不在榜单上,榜单不应发生任何变化。 它应该原样返回。

removePlayer({ 'Dave Thomas': 0 }, 'Dave Thomas');
// => {}

removePlayer({ 'Dave Thomas': 0 }, 'Rose Fanaras');
// => { 'Dave Thomas': 0 }

4. 提高玩家的分数

如果玩家在街机厅又玩完一局,一定的分数会加到榜单上他之前的分数里。 实现updateScore函数,它接受 3 个形参:

  • 第一个形参是一个已有的高分榜对象。
  • 第二个形参是要提高分数的玩家的名字。
  • 第三个形参是你想要加到已存高分上的分数。

更新完成后,该函数应返回这个高分榜。

updateScore({ 'Freyja Ćirić': 12771008 }, 'Freyja Ćirić', 73);
// => {"Freyja Ćirić", 12771081}

5. 应用周一奖励分

街机厅在周一另有一块独立的榜单。 当天结束时,这块榜单上的每位玩家都会获得 100 分额外奖励。

实现applyMondayBonus函数,它接受一个高分榜。 该函数会为榜单上的每位玩家加上奖励分。 之后返回这个榜单。

const scoreBoard = {
  'Dave Thomas': 44,
  'Freyja Ćirić': 539,
  'José Valim': 265,
};

applyMondayBonus(scoreBoard);
// => { 'Dave Thomas': 144, 'Freyja Ćirić': 639, 'José Valim': 365 }
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
JavaScript Exercism

准备好开始 高分榜 了吗?

注册 Exercism,借助 37 个概念159 个练习 和真人导师指导,学习并掌握 JavaScript,全部免费。