百度&阿里编程题:模拟实现一个 localStorage
sisterAn opened this issue · comments
可参考来源:
第 103 题:模拟实现一个 localStorage
一、localStorage 特性
1. Storage Interface
- getItem(key)
- setItem(key, value)
- removeItem(key)
- clear()
- key(index)
- length:readonly
2. 持久化存储
刷新、关闭页面依然存在
3. localStorage 中的键值对总是以字符串的形式存储 key.toString() value.toString()
localStorage.setItem('pzijun', 100)
localStorage.getItem('pzijun')
// "100"
var a = {a: 1}
localStorage.setItem(a, {a:1})
localStorage.getItem(a)
// "[object Object]"
var b = {}
localStorage.setItem(b, '11')
localStorage.getItem(b)
// "11"
localStorage.getItem(a)
// "11"
4. same-origin rules 特定于页面的协议,以及隐身模式等的区别
当浏览器进入隐身模式(private browsing mode)的时候,会创建一个新的、临时的、空的数据库,用以存储本地数据(local storage data)。当浏览器关闭时,里面的所有数据都将被丢弃。
二、用 cookie 模拟 localStorage
参考 https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie
window.LS = {
getItem: function (sKey) {
if (!sKey || !this.hasOwnProperty(sKey)) {
return null;
}
return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
},
key: function (nKeyId) {
return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]);
},
setItem: function (sKey, sValue) {
if (!sKey) {
return;
}
document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
this.length = document.cookie.match(/\=/g).length;
},
length: 0,
removeItem: function (sKey) {
if (!sKey || !this.hasOwnProperty(sKey)) {
return;
}
document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
this.length--;
},
hasOwnProperty: function (sKey) {
return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
}
};
window.LS.length = (document.cookie.match(/\=/g) || window.LS).length;
if (!window.localStorage) {
window.localStorage = window.LS;
}
测试:
LS.setItem('pzijun', 100)
LS.getItem('pzijun')
// "100"
var a = {
a: 1
}
LS.setItem(a, {
a: 1
})
LS.getItem(a)
// "[object Object]"
var b = {}
LS.setItem(b, '11')
LS.getItem(b)
// "11"
LS.getItem(a)
// "11"
另外还有容量控制、异常处理等,这里不再讨论,感兴趣的可以自己尝试实现下
三、扩展 localStorage 支持 expires 过期时间
(function () {
var getItem = localStorage.getItem.bind(localStorage)
var setItem = localStorage.setItem.bind(localStorage)
var removeItem = localStorage.removeItem.bind(localStorage)
localStorage.getItem = function (keyName) {
var expires = getItem(keyName + '_expires')
if (expires && new Date() > new Date(Number(expires))) {
removeItem(keyName)
removeItem(keyName + '_expires')
}
return getItem(keyName)
}
localStorage.setItem = function (keyName, keyValue, expires) {
if (typeof expires !== 'undefined') {
var expiresDate = new Date(expires).valueOf()
setItem(keyName + '_expires', expiresDate)
}
return setItem(keyName, keyValue)
}
})()
测试:
localStorage.setItem('key', 'value', new Date() + 10000) // 10 秒钟后过期
localStorage.getItem('key')
class LocalStorageFake {
constructor() {
this.storage = {};
}
getItem(key) {
return this.storage[key];
}
setItem(key, value) {
this.storage[key] = value;
}
removeItem(key) {
delete this.storage[key];
}
clear() {
this.storage = {};
}
}