我正在寻找一种方法来冻结原生ES6地图。
Object.freeze
和 Object.seal
似乎不起作用:
let myMap = new Map([["key1", "value1"]]);
// Map { 'key1' => 'value1' }
Object.freeze(myMap);
Object.seal(myMap);
myMap.set("key2", "value2");
// Map { 'key1' => 'value1', 'key2' => 'value2' }
这是预期的行为,因为冻结冻结的属性 objects
和 maps
不是 objects
或者这可能是一个错误/尚未实现?
是的,我知道,我应该使用 Immutable.js,但有没有办法用本机ES6地图做到这一点?
@loganfsmyth,你的回答给了我一个想法,这个怎么样:
function freezeMap(myMap){
if(myMap instanceof Map) {
myMap.set = function(key){
throw('Can\'t add property ' + key + ', map is not extensible');
};
myMap.delete = function(key){
throw('Can\'t delete property ' + key + ', map is frozen');
};
myMap.clear = function(){
throw('Can\'t clear map, map is frozen');
};
}
Object.freeze(myMap);
}
这对我来说很完美:)
更新了点 @Bergi 在评论中:
var mapSet = function(key){
throw('Can\'t add property ' + key + ', map is not extensible');
};
var mapDelete = function(key){
throw('Can\'t delete property ' + key + ', map is frozen');
};
var mapClear = function(){
throw('Can\'t clear map, map is frozen');
};
function freezeMap(myMap){
myMap.set = mapSet;
myMap.delete = mapDelete;
myMap.clear = mapClear;
Object.freeze(myMap);
}
没有,你可以写一个包装来做到这一点。 Object.freeze
锁定对象的属性,但同时 Map
实例是对象,它们存储的值不是属性,因此冻结对它们没有影响,就像任何其他隐藏了内部状态的类一样。
在支持扩展内置的真实ES6环境中(不是巴别塔),你可以这样做:
class FreezableMap extends Map {
set(...args){
if (Object.isFrozen(this)) return this;
return super.set(...args);
}
delete(...args){
if (Object.isFrozen(this)) return false;
return super.delete(...args);
}
clear(){
if (Object.isFrozen(this)) return;
return super.clear();
}
}
如果您需要在ES5环境中工作,您可以轻松地为一个包装类 Map
而不是扩展 Map
类。