映射
我们在上一章中看到了映射(map)这个词,用于一个操作,通过对元素应用函数来转换数据结构。 令人困惑的是,在编程时,同一个词也被用于相关而不同的事物。
映射(名词)是将值(键)与其他值相关联的数据结构。 例如,你可能想要将姓名映射到年龄。 为此可以使用对象。
let ages = {
Boris: 39,
Liang: 22,
Júlia: 62
};
console.log(`Júlia is ${ages["Júlia"]}`);
// → Júlia is 62
console.log("Is Jack's age known?", "Jack" in ages);
// → Is Jack's age known? false
console.log("Is toString's age known?", "toString" in ages);
// → Is toString's age known? true
在这里,对象的属性名称是人们的姓名,并且该属性的值为他们的年龄。 但是我们当然没有在我们的映射中列出任何名为toString
的人。 似的,因为简单对象是从Object.prototype
派生的,所以它看起来就像拥有这个属性。
因此,使用简单对象作为映射是危险的。 有几种可能的方法来避免这个问题。 首先,可以使用null
原型创建对象。 如果将null
传递给Object.create
,那么所得到的对象将不会从Object.prototype
派生,并且可以安全地用作映射。
console.log("toString" in Object.create(null));
// → false
对象属性名称必须是字符串。 如果你需要一个映射,它的键不能轻易转换为字符串 - 比如对象 - 你不能使用对象作为你的映射。
幸运的是,JavaScript 带有一个叫做Map
的类,它正是为了这个目的而编写。 它存储映射并允许任何类型的键。
let ages = new Map();
ages.set("Boris", 39);
ages.set("Liang", 22);
ages.set("Júlia", 62);
console.log(`Júlia is ${ages.get("Júlia")}`);
// → Júlia is 62
console.log("Is Jack's age known?", ages.has("Jack"));
// → Is Jack's age known? false
console.log(ages.has("toString"));
// → false
set
,get
和has
方法是Map
对象的接口的一部分。 编写一个可以快速更新和搜索大量值的数据结构并不容易,但我们不必担心这一点。 其他人为我们实现,我们可以通过这个简单的接口来使用他们的工作。
如果你确实有一个简单对象,出于某种原因需要将它视为一个映射,那么了解Object.keys
只返回对象的自己的键,而不是原型中的那些键,会很有用。 作为in
运算符的替代方法,你可以使用hasOwnProperty
方法,该方法会忽略对象的原型。
console.log({x: 1}.hasOwnProperty("x"));
// → true
console.log({x: 1}.hasOwnProperty("toString"));
// → false