Ruby 为什么在冻结哈希本身之前冻结哈希值?
我注意到有些人做了Ruby 为什么在冻结哈希本身之前冻结哈希值?,ruby,performance,Ruby,Performance,我注意到有些人做了{'foo':'bar'.freeze}.freeze,而不仅仅是{'foo':'bar'}.freeze 更好吗?如果是,原因是什么?hash.freeze冻结哈希本身,但不冻结其值。这意味着您将无法再分配新值或删除键,但仍可以更改现有值: hash = {a: 'hello'}.freeze hash[:b] = 'there' #=> exception! hash[:a] = 'hello there' #=> exception! hash[:a].upc
{'foo':'bar'.freeze}.freeze
,而不仅仅是{'foo':'bar'}.freeze
更好吗?如果是,原因是什么?
hash.freeze
冻结哈希本身,但不冻结其值。这意味着您将无法再分配新值或删除键,但仍可以更改现有值:
hash = {a: 'hello'}.freeze
hash[:b] = 'there' #=> exception!
hash[:a] = 'hello there' #=> exception!
hash[:a].upcase! #=> no exception
hash #=> {a: 'HELLO'}
在第三行中,我们尝试为现有密钥分配一个新字符串,但失败了。但是在第四行中,我们直接修改字符串的实例。散列只是保留对其他对象的引用,所以修改字符串根本不会影响散列
如果同时冻结字符串,则情况会有所不同:
hash = {a: 'hello'.freeze}.freeze
hash[:a].upcase! #=> exception!
默认情况下,Ruby字符串是可变的。因此,第一种方法阻止某人使用冻结字符串和冻结哈希不是一回事。关于@engineersmnky的评论,假设
h={:a=>'cat'}。冻结
。然后,h.object#id#=>1820
和h[:a].object#id#=>1840
。无法更改哈希,因为它已冻结:h[:a]='dog'#=>FrozenError:无法修改冻结的哈希:{:a=>“cat”}
。但是,我们可以使用另一个字符串h[:a]
:替换('dog')#=>“dog”。注意h#=>{:a=>'dog'}
,h.object#id#=>1820
和h[:a]。object#id#=>1840
…现在也冻结:a
的值:h[:a]。冻结#=>“dog”
。然后h[:a]。替换('pig')#=>冻结错误:无法修改冻结字符串:“dog”
。