我如何检测和使用 localStorage:一个简单的 JavaScript 模式
传统的方法
以下是检测 localStorage
支持的方法:
// Feature test
var hasStorage = (function() {
try {
localStorage.setItem(mod, mod);
localStorage.removeItem(mod);
return true;
} catch (exception) {
return false;
}
}());
请注意
,访问全局localStorage
对象可能会引发异常,因此需要在该测试的try-catch
块内完成。
Modernizr 就是这样做的(并在源代码中广泛记录了该技术)。 它可以根据我们希望支持的浏览器和边缘情况进行一些简化,但目前这是最强大的功能检测。
通过上面的代码片段,我们可以在代码中使用 localStorage
,如下所示
if (hasStorage) {
// Use `localStorage` here, e.g.
localStorage.setItem('foo', 'bar');
localStorage.lol = 'wat';
localStorage.removeItem('foo');
}
当然,这并不是什么新鲜事。 那我为什么要写这个? 好吧,我一直在使用一种略有不同的技术,它有一些优点,我想分享一下。
新模式
让我们看看如果我们稍微调整一下上面的脚本会发生什么:
// Feature detect + local reference
var storage = (function() {
var uid = new Date;
var result;
try {
localStorage.setItem(uid, uid);
result = localStorage.getItem(uid) == uid;
localStorage.removeItem(uid);
return result && localStorage;
} catch (exception) {}
}());
与之前的代码片段相比,变化不大。 有以下三个区别:
-
此代码段实际上检测
localStorage
是否正常工作,方法是检查getItem()
返回的值是否与使用setItem()
设置的值相同。 -
如果
localStorage
特征检测成功,则其结果为真。 所以我们追加&& localStorage
,如果测试成功,这会导致存储变量成为对全局localStorage
对象的引用。 换句话说,如果不支持localStorage
,storage === undefined
,这是错误的。 如果支持,storage === window.localStorage
,这是真的。 - 我们没有从 catch 块中返回 false,而是什么都不返回。 如果捕获到错误,存储将是未定义的,这是错误的。
我们可以更进一步,避免对 localStorage
(如果可用)的重复范围查找,如下所示:
// Feature detect + local reference
var storage = (function() {
var uid = new Date;
var storage;
var result;
try {
(storage = window.localStorage).setItem(uid, uid);
result = storage.getItem(uid) == uid;
storage.removeItem(uid);
return result && storage;
} catch (exception) {}
}());
正如 Juriy “kangax” Zaytsev 指出的那样,完全避免使用匿名函数是可能的:
// Feature detect + local reference
var storage;
var fail;
var uid;
try {
uid = new Date;
(storage = window.localStorage).setItem(uid, uid);
fail = storage.getItem(uid) != uid;
storage.removeItem(uid);
fail && (storage = false);
} catch (exception) {}
它工作得很好,而且由于减少了函数调用的数量,甚至比前面的代码片段更有效。
无论如何,我们可以像这样使用这些片段中的任何一个:
if (storage) {
// Use `storage` here, e.g.
storage.setItem('foo', 'bar');
storage.lol = 'wat';
storage.removeItem('foo');
}
再简单不过了!
有用吗?
我最喜欢这种模式是因为它的优雅,但是——假设你的代码在它自己的范围内以防止将变量泄漏到全局范围——还有一些(次要的)性能优势:
-
只有一个变量(
storage
)——它既可以用来检查是否支持localStorage
也可以用来操作它。 -
通过直接使用局部存储变量而不是全局
localStorage
对象,范围查找保持在最低限度。 -
始终使用引用
localStorage
的局部变量会导致压缩/缩小后的文件大小更小。 -
这是一个边缘案例,但如果我们需要将整个 Web 应用程序从
localStorage
切换到sessionStorage
,我们甚至不必更改变量名称。 只需将出现的localStorage
替换为sessionStorage
即可。 (这些 API 是相同的,甚至特征检测也可以用相同的方式完成。)
相关文章
Do you understand JavaScript closures?
发布时间:2025/02/21 浏览次数:108 分类:JavaScript
-
The function of a closure can be inferred from its name, suggesting that it is related to the concept of scope. A closure itself is a core concept in JavaScript, and being a core concept, it is naturally also a difficult one.
Do you know about the hidden traps in variables in JavaScript?
发布时间:2025/02/21 浏览次数:178 分类:JavaScript
-
Whether you're just starting to learn JavaScript or have been using it for a long time, I believe you'll encounter some traps related to JavaScript variable scope. The goal is to identify these traps before you fall into them, in order to av
How much do you know about the Prototype Chain?
发布时间:2025/02/21 浏览次数:150 分类:JavaScript
-
The prototype chain can be considered one of the core features of JavaScript, and certainly one of its more challenging aspects. If you've learned other object-oriented programming languages, you may find it somewhat confusing when you start
如何在 JavaScript 中合并两个数组而不出现重复的情况
发布时间:2024/03/23 浏览次数:86 分类:JavaScript
-
本教程介绍了如何在 JavaScript 中合并两个数组,以及如何删除任何重复的数组。