尝试在不可扩展对象上定义属性时,弱映射填充项引发错误
WeakMap polyfill throwing error when trying to define property on inextensible object
WeakMap polyfill 在尝试定义不可扩展对象的属性时引发错误。这些位于一堆节点,javascript代码和库的中间,所以我实际上无法指出导致问题的原因。还有许多其他库也有自己的 polyfill。很难调试哪个库导致错误。而且,错误仅在IE10上。
为了摆脱它,我在定义类似(上面文件中的第 26 行(的属性之前添加了一个检查器:
if (entry && entry[0] === key) {
entry[1] = value;
}
else if (Object.isExtensible(key)) {
defineProperty(key, this.name, {
value: [ key, value ],
writable: true
});
}
我的问题是,按照上面的代码修复它是否安全/正确?如果没有,我应该如何解决我的问题?
据我所知,weakMap
polyfill 仅用于将可扩展对象用作键。 它根本不适用于不可扩展的对象。
您的修改已经做到了,所以它不会引发异常,但这样不可扩展的项目也不会在weakMap
中。 因此,您的修复并不是真正的修复。 必须重写该特定的 polyfill 才能处理不可扩展的键。 这不是一个简单的解决方案,因为它需要一种概念上不同的方法。
还有许多其他填充物采用不同的方法。 我还没有研究在这方面哪些可能更好。 我怀疑这是实际"弱"(例如允许垃圾收集(与可以处理不可扩展对象之间的一点难题。 根本的问题是,如果你要变得弱,那么你就不能存储对对象本身的引用。 因此,您需要存储对对象的某些字符串表示形式的引用。 好吧,JS对象没有内置的保证唯一字符串表示形式。 因此,通常的解决方法是使用某种计数器投币并将其作为属性存储在对象上,然后将该字符串表示形式存储在地图中。 但是,如果对象不可扩展,那么您也无法这样做。 因此,您只能将实际的对象引用存储在地图中,但是它不再真正"弱"。 你可以看到你是如何被卡住的。
我认为这是填充物无法完全达到真实情况的一种情况。 在这方面,不同的填充物将有不同的权衡。 你选择了一个真正弱的,但要求对象可扩展,以便可以添加属性。
就像我的问题一样,我想要一个对其他功能或插件没有巨大影响的解决方案,所以这是我对这个问题的修复。该修复基于上述@jfriend00答案以及互联网上其他实现的参考。
var defineProperty = Object.defineProperty;
var counter = Date.now() % 1e9;
var FrozenStore = function() {
this.a = [];
};
var findFrozen = function(store, key){
return store.a.forEach(function(it){
if (it[0] === key) {
return it;
}
});
};
var findIndexFrozen = function(store, key){
return store.a.forEach(function(it, id){
if (it[0] === key) {
return id;
}
});
};
FrozenStore.prototype = {
get: function(key){
var entry = findFrozen(this, key);
if (entry) return entry[1];
},
has: function(key){
return !!findFrozen(this, key);
},
set: function(key, value){
var entry = findFrozen(this, key);
if (entry) entry[1] = value;
else this.a.push([key, value]);
},
"delete": function(key){
var index = findIndexFrozen(this, key);
if (~index) this.a.splice(index, 1);
return !!~index;
}
};
var WeakMap = function() {
this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
};
var frozenStore = function(that){
return that._l || (that._l = new FrozenStore);
};
WeakMap.prototype = {
set: function(key, value) {
var entry = key[this.name];
if (entry && entry[0] === key) {
entry[1] = value;
} else {
if (!Object.isExtensible(key)) {
frozenStore(this).set(key, value);
} else {
defineProperty(key, this.name, {
value: [ key, value ],
writable: true
});
}
}
return this;
},
get: function(key) {
var entry;
if ((entry = key[this.name]) && entry[0] === key) {
return entry[1];
} else if (!Object.isExtensible(key)) {
frozenStore(this).get(key);
} else {
return undefined;
}
},
"delete": function(key) {
var entry = key[this.name];
if (!entry || entry[0] !== key) return false;
if (!Object.isExtensible(key)) frozenStore(this)['delete'](key);
entry[0] = entry[1] = undefined;
return true;
},
has: function(key) {
var entry = key[this.name];
if (!entry) return false;
if(!Object.isExtensible(key)) return frozenStore(this).has(key);
return entry[0] === key;
}
};
window.WeakMap = WeakMap;
这引入了FrozenStore,它将管理添加到WeakMap的所有非可扩展密钥。我不确定它是否打破了WeakMap的概念,但它确实将我从这个问题中解救出来。
- 如何设置html元素填充的动画
- 如何使用jquery在填充自动完成的值后使文本框只读
- 如何在映射数组中添加换行符
- 如何通过ajax刷新JSF填充的javascript变量
- ng映射方向备选方案
- 无法通过数组映射绑定
- ReactJS映射:如何仅在url变量不为空时呈现html链接
- 用与线条相同的颜色填充多折线图上的点
- 用每小时的差值填充数组/列表-从下拉列表中给定两个时间值
- 带有填充属性的SVG矩形显示在包含元素的上方插入框阴影
- 用我的json数据填充JQuery DataTable
- 复选框列表 将数组格式化为 JSON 并在 ng-repeat 中映射后未填充
- 在用数组填充初始化的数组上使用数组映射的意外行为
- 尝试在不可扩展对象上定义属性时,弱映射填充项引发错误
- 使用knockout映射JSON无法填充类型定义的对象属性
- 需要等待MarkerWithLabel完成对映射的填充
- 映射函数而不是填充变量
- 表映射的第一行和第一个td从json对象填充
- 为区域构建具有可选和不同背景(颜色和图像填充)的复杂图像映射
- 用spring映射url填充下拉框