Hash 可以看作是一个 关联数组,它对每一个值都绑定了一个唯一的键(值并不必须是唯一的),
然而,它不能保证迭代时元素的顺序始终一致。因为 JavaScript 程序语言的特性,每个对象实际上都是一个 hash,但是,本篇所述的
Hash
增加了许多方法,让你能够轻松地枚举键和值、迭代“键/值”对、 合并两个 hash、将 hash 编码成为一个查询字符串等等。
创建一个 hash
构造一个 Hash
实例有两种方法:第一种是使用 new
关键字实例化一个 JavaScript
对象(new Hash(obj)
)。第二种是使用 $H
函数。传递一个 JavaScript 对象或是一个 Hash 给 $H
,$H
函数会克隆它们,并不会对原始对象造成任何影响。
对于上述两种构造方法,你也可以不传递任何参数而调用它们。它们将返回一个空的 hash。
在 Prototype 1.6 中的后向兼容性变更
后向兼容性变更 - 虽然新版本的 Hash 与之前的版本具有相同的目标,但是新版本的 Hash
不再兼容先前版本的 Hash 类型。
现在,不能再通过 Hash
实例的属性来访问“键/值”对,它们是私有的,这是为了防止在 Hash
实例上定义的属性和混入的方法引起键的冲突。这意味着你必须使用 Hash#get(key)、 Hash#set(key, value) 和 Hash#unset(key) 实例方法来访问、设置或删除“键/值”对。例如:
var myhash = new Hash();
// 老的 API --> 新的 API
myhash.name = "Bob"; --> myhash.set('name', 'Bob');
myhash.name; --> myhash.get('name');
delete myhash.name; --> myhash.unset('name');
你也应该了解关于 Hash API 的其它变更:
-
$H(object)
快捷方法现在完全等同于 new
Hash(object)
。无论参数是一个对象还是另一个 Hash
,它们都返回一个新的对象。
-
Hash#merge
返回一个新的 Hash
,而不再是对调用该方法的实例对象进行修改。
-
Hash#update
是 Hash#merge
的一个破坏性版本,它会修改调用该方法的实例对象。
-
Hash#clone
返回一个新的当前 Hash 对象的克隆实例。
-
Hash#toObject
返回一个当前 Hash
内部对象的复本。
译注:Prototype 使用了一个单独的内部对象来存储“键/值”对。
-
Hash.toQueryString
现在是 Object.toQueryString
的一个别名。(Hash.toQueryString
已不推荐使用,在将来的 Prototype 版本中,这个方法将会被移除。)
-
Hash#remove
已经被 Hash#unset
取代。
-
Hash.toJSON
已经被 Object.toJSON
或
Hash#toJSON
实例方法取代。
注意,对于 Prototype 的早期版本(< 1.6)
传递一个 hash 到 $H
并不会克隆它。
因为混入了 Enumerable,同时,它还有自己的方法,所以
Hash
不是所有的名称都可以用作“键”的。如果新增的键的名称与 Hash
的任何一个方法同名,则那个方法不能再被调用。 即使因为你不需要调用那个方法而侥幸获得成功,但仍然会有问题:
var h = new Hash({ ... });
h['each'] = 'my own stuff';
h.map();
// -> 错误,因为 'each' 不再是一个函数
在 Enumerable 中,最重要的方法是 each, 因为几乎每一个其它的方法都需要它——覆盖它将导致我们的 hash
实例成为一个废物。你也不能抱着侥幸心理使用 _each
,因为它也是 Enumerable
内部的一个重要方法。