由于localStorage(目前)只支持字符串作为值,为了做到这一点,对象需要在存储之前进行字符串化(存储为JSON-string),对于值的长度是否有定义的限制。

有人知道是否有一个适用于所有浏览器的定义吗?


当前回答

查找可以存储在localStorage中的单个字符串的最大长度

这个代码片段将找到每个域可以存储在localStorage中的String的最大长度。

//Clear localStorage
for (var item in localStorage) delete localStorage[item];

window.result = window.result || document.getElementById('result');

result.textContent = 'Test running…';

//Start test
//Defer running so DOM can be updated with "test running" message
setTimeout(function () {

    //Variables
    var low = 0,
        high = 2e9,
        half;

    //Two billion may be a little low as a starting point, so increase if necessary
    while (canStore(high)) high *= 2;


    //Keep refining until low and high are equal
    while (low !== high) {
        half = Math.floor((high - low) / 2 + low);

        //Check if we can't scale down any further
        if (low === half || high === half) {
            console.info(low, high, half);
            //Set low to the maximum possible amount that can be stored 
            low = canStore(high) ? high : low;
            high = low;
            break;
        }


        //Check if the maximum storage is no higher than half
        if (storageMaxBetween(low, half)) {
            high = half;
            //The only other possibility is that it's higher than half but not higher than "high"
        } else {
            low = half + 1;
        }

    }

    //Show the result we found!
    result.innerHTML = 'The maximum length of a string that can be stored in localStorage is <strong>' + low + '</strong> characters.';

    //Functions
    function canStore(strLen) {
        try {
            delete localStorage.foo;
            localStorage.foo = Array(strLen + 1).join('A');
            return true;
        } catch (ex) {
            return false;
        }
    }


    function storageMaxBetween(low, high) {
        return canStore(low) && !canStore(high);
    }

}, 0);
<h1>LocalStorage single value max length test</h1>

<div id='result'>Please enable JavaScript</div>

请注意,在JavaScript中字符串的长度是有限的;如果您希望查看localStorage中可以存储的最大数据量,而不限于单个字符串,则可以使用此答案中的代码。

编辑:堆栈片段不支持localStorage,所以这里有一个到JSFiddle的链接。

结果

Chrome(45.0.2454.101): 5242878个字符 Firefox(40.0.1): 5242883个字符 Internet Explorer(11.0.9600.18036): 16386 122066 122070个字符

每次在Internet Explorer中运行都会得到不同的结果。

其他回答

我编写了这段简单的代码,以字节为单位测试localStorage的大小。

https://github.com/gkucmierz/Test-of-localStorage-limits-quota

const check = bytes => {
  try {
    localStorage.clear();
    localStorage.setItem('a', '0'.repeat(bytes));
    localStorage.clear();
    return true;
  } catch(e) {
    localStorage.clear();
    return false;
  }
};

Github页面:

https://gkucmierz.github.io/Test-of-localStorage-limits-quota/

我在桌面谷歌chrome, opera, firefox, brave和移动chrome上有相同的结果,这是~10Mbytes

和一半小的结果safari约4mb

您不希望将大对象字符串化到单个localStorage条目中。这将是非常低效的——每次有细微的细节变化时,整个东西都必须被解析和重新编码。此外,JSON不能在对象结构中处理多个交叉引用,并且删除了许多细节,例如构造函数、数组的非数值属性、稀疏条目中的内容等。

相反,您可以使用Rhaboo。它使用大量的localStorage条目来存储大型对象,因此您可以快速地进行小的更改。恢复的对象是保存的对象的更准确的副本,API非常简单。例如:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');

顺便说一句,这是我写的。

我真的很喜欢cdmckay的答案,但它并不真的看起来很好,实时检查大小:它太慢了(对我来说2秒)。这是改进的版本,它更快,更准确,也有一个选项来选择误差的大小(默认为250000,误差越小-计算时间越长):

function getLocalStorageMaxSize(error) {
  if (localStorage) {
    var max = 10 * 1024 * 1024,
        i = 64,
        string1024 = '',
        string = '',
        // generate a random key
        testKey = 'size-test-' + Math.random().toString(),
        minimalFound = 0,
        error = error || 25e4;

    // fill a string with 1024 symbols / bytes    
    while (i--) string1024 += 1e16;

    i = max / 1024;

    // fill a string with 'max' amount of symbols / bytes    
    while (i--) string += string1024;

    i = max;

    // binary search implementation
    while (i > 1) {
      try {
        localStorage.setItem(testKey, string.substr(0, i));
        localStorage.removeItem(testKey);

        if (minimalFound < i - error) {
          minimalFound = i;
          i = i * 1.5;
        }
        else break;
      } catch (e) {
        localStorage.removeItem(testKey);
        i = minimalFound + (i - minimalFound) / 2;
      }
    }

    return minimalFound;
  }
}

测试:

console.log(getLocalStorageMaxSize()); // takes .3s
console.log(getLocalStorageMaxSize(.1)); // takes 2s, but way more exact

对于标准错误,这工作得快得多;而且,在必要的时候,它可以更加精确。

引用维基百科关于Web存储的文章:

Web存储可以简单地看作是对cookie的改进,提供了更大的存储容量(在谷歌Chrome(https://plus.google.com/u/0/+FrancoisBeaufort/posts/S5Q9HqDB8bh)、Mozilla Firefox和Opera中,每个源的存储容量为10mb;在Internet Explorer中,每个存储区域为10mb)和更好的编程接口。

我还引用了John Resig在2007年1月发表的一篇文章:

Storage Space It is implied that, with DOM Storage, you have considerably more storage space than the typical user agent limitations imposed upon Cookies. However, the amount that is provided is not defined in the specification, nor is it meaningfully broadcast by the user agent. If you look at the Mozilla source code we can see that 5120KB is the default storage size for an entire domain. This gives you considerably more space to work with than a typical 2KB cookie. However, the size of this storage area can be customized by the user (so a 5MB storage area is not guaranteed, nor is it implied) and the user agent (Opera, for example, may only provide 3MB - but only time will tell.)

我将二进制测试压缩到我使用的这个函数中:

function getStorageTotalSize(upperLimit/*in bytes*/) {
    var store = localStorage, testkey = "$_test"; // (NOTE: Test key is part of the storage!!! It should also be an even number of characters)
    var test = function (_size) { try { store.removeItem(testkey); store.setItem(testkey, new Array(_size + 1).join('0')); } catch (_ex) { return false; } return true; }
    var backup = {};
    for (var i = 0, n = store.length; i < n; ++i) backup[store.key(i)] = store.getItem(store.key(i));
    store.clear(); // (you could iterate over the items and backup first then restore later)
    var low = 0, high = 1, _upperLimit = (upperLimit || 1024 * 1024 * 1024) / 2, upperTest = true;
    while ((upperTest = test(high)) && high < _upperLimit) { low = high; high *= 2; }
    if (!upperTest) {
        var half = ~~((high - low + 1) / 2); // (~~ is a faster Math.floor())
        high -= half;
        while (half > 0) high += (half = ~~(half / 2)) * (test(high) ? 1 : -1);
        high = testkey.length + high;
    }
    if (high > _upperLimit) high = _upperLimit;
    store.removeItem(testkey);
    for (var p in backup) store.setItem(p, backup[p]);
    return high * 2; // (*2 because of Unicode storage)
}

它还在测试之前备份内容,然后恢复它们。

它的工作原理:它将大小增加一倍,直到达到限制或测试失败。然后它存储低和高之间的距离的一半,并每次减去/增加一半(失败时减去,成功时增加);磨炼成合适的值。

默认情况下,upperLimit为1GB,仅限制在开始二分查找之前以指数方式向上扫描的距离。我怀疑这种情况是否需要改变,但我总是未雨绸缪。;)

铬:

> getStorageTotalSize();
> 10485762
> 10485762/2
> 5242881
> localStorage.setItem("a", new Array(5242880).join("0")) // works
> localStorage.setItem("a", new Array(5242881).join("0")) // fails ('a' takes one spot [2 bytes])

IE11、Edge和FireFox也报告了相同的最大大小(10485762字节)。