此代码总结了我的问题:
localStorage.setItem('getItem', 4)
undefined
localStorage.getItem
function getItem() { [native code] }
localStorage['getItem'] = 'user'
"user"
localStorage.getItem
"user"
localStorage.getItem('getItem')
TypeError: Property 'getItem' of object #<Storage> is not a function
使用setItem
方法或使用属性访问器更改localStorage的反应方式。
这是一个错误吗?规格不一致?还有别的吗?
我觉得我应该在某个地方举报,但不知道在哪里。
答案 0 :(得分:5)
使用setItem方法或使用属性访问器更改localStorage的反应方式。
这是一个错误吗?
看起来不像。来自spec:
当调用setItem(),removeItem()和clear()方法时 与本地存储区域关联的存储对象x,如果 方法做了什么,然后在每个Document对象中 Window对象的localStorage属性的Storage对象是关联的 除了x之外,存储区域必须相同 解雇了,如下所述。
localStorage对象是IDL attribute,其中包含对Storage接口的引用。 Storage接口扩展了Object.prototype,它引入了额外的属性,并且还定义了自己的属性集。
setItem
方法将属性存储在存储列表中。当对象属性发生更改时,该对象还会触发事件,并在这些情况下更新存储区域。
因此setItem
的预期行为是将密钥值对存储在存储列表中。 getItem
的预期行为是从存储列表中提取与密钥关联的值。
那么当我们尝试直接访问属性时,预期的行为是什么?该行表示键值列表充当“支持的属性”:
Storage对象上支持的属性名称是每个名称的键 键/值对当前存在于与该列表关联的列表中 对象
这是什么意思?这意味着those properties are mapped to the getters and setters defined by the interface spec。对于存储,接口规范如下所示:
interface Storage {
readonly attribute unsigned long length;
DOMString? key(unsigned long index);
getter DOMString getItem(DOMString key);
setter creator void setItem(DOMString key, DOMString value);
deleter void removeItem(DOMString key);
void clear();
};
因此localStorage["x"]
映射到getItem("x")
的值,该值在存储列表中返回“x”的值,localStorage["x"] = y
将映射到setItem("x",y)
。
但是,只有在对象上没有该名称的本机属性时才会运行这些属性,除非在接口上设置了overridebuiltins属性(它不是用于存储)。
如果界面上出现[OverrideBuiltins]扩展属性, 它表示对于实现接口的平台对象, 对应于所有对象支持的属性的属性 无论其他什么,名称都会出现在对象上 属性存在于对象或其原型链上。这意味着 命名属性将始终隐藏任何属性 否则出现在对象上。这与通常情况形成对比 行为,仅当存在时才会公开命名属性 没有在对象本身或其他地方具有相同名称的属性 它的原型链。
因此,对于属性,我们应该期望如果在对象上定义函数,它将始终在请求上访问/设置该函数。否则,它将检查存储列表并查看它是否有值并更改或返回。
规范中的预期行为以及我们在测试时发现的内容是setItem
和getItem
会将预先存在的属性/函数的值存储为键/值对,并访问它们,不覆盖现有值。当我们尝试直接通过localStorage [“getItem”]访问或修改这些值时,我们将改为命中本地属性,因为默认情况下“支持的属性”规范要求不覆盖内置属性。