Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

百度&阿里编程题:模拟实现一个 localStorage #108

Open
sisterAn opened this issue Sep 16, 2020 · 1 comment
Open

百度&阿里编程题:模拟实现一个 localStorage #108

sisterAn opened this issue Sep 16, 2020 · 1 comment

Comments

@sisterAn
Copy link
Owner

sisterAn commented Sep 16, 2020

可参考来源:
第 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')
@broXue
Copy link

broXue commented Sep 16, 2020

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 = {};
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants