如何在JavaScript中创建和读取cookie的值?
当前回答
通过类似sessionStorage和localStorage的接口:
const cookieStorage = {
getItem: (key) {
const cookies = document.cookie.split(';')
.map(cookie => cookie.split('='))
.reduce(
(accumulation, [key, value]) => ({...accumulation, [key.trim()]: value}),
{}
)
return cookies[key]
},
setItem: (key, value) {
document.cookie = `${key}=${value}`
},
}
它的用法cookieStorage。setItem(", ")和cookieStorage.getItem(")。
其他回答
下面是前面提到的w3schools的例子。
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
Mozilla创建了一个简单的框架,用于读取和写入cookie,并提供了完整的unicode支持以及如何使用它的示例。
一旦包含在页面中,您可以设置cookie:
docCookies.setItem(name, value);
读饼干:
docCookies.getItem(name);
或者删除cookie:
docCookies.removeItem(name);
例如:
// sets a cookie called 'myCookie' with value 'Chocolate Chip'
docCookies.setItem('myCookie', 'Chocolate Chip');
// reads the value of a cookie called 'myCookie' and assigns to variable
var myCookie = docCookies.getItem('myCookie');
// removes the cookie called 'myCookie'
docCookies.removeItem('myCookie');
查看Mozilla文档中的更多示例和详细信息。饼干页面。
这个简单的js文件的一个版本在github上。
性能基准测试
ES6版本的一些流行getCookie函数的比较(我的改进): https://www.measurethat.net/Benchmarks/Show/16012/5/getcookie-for-vs-forof-vs-indexof-vs-find-vs-reduce
TL;博士:……版本接缝为现实生活中的cookie数据最快:)
重要的是:文档。如果path=/和当前页面路径有相同名称的Cookie, Cookie可以提供重复的Cookie名称。路径= /常见问题解答)。但是当前路径的cookie总是字符串中的第一个,所以在使用这里提供的其他答案的reduce()版本时要注意这一点(它返回最后找到的cookie而不是第一个)。 固定减少()版本是进一步在我的答案。
. .的版本:
对于实际基准测试数据集(10个具有长值的cookie)来说是最快的。但是性能结果与普通for循环和Array.find()几乎相同,所以使用你喜欢的:)
function getCookieForOf(name) {
const nameEQ = name + '=';
for (const cookie of document.cookie.split('; ')) {
if (cookie.indexOf(nameEQ) === 0) {
const value = cookie.substring(nameEQ.length);
return decodeURIComponent(value); // returns first found cookie
}
}
return null;
}
IndexOf版本
在1000个具有短值的cookie的人工测试集中,速度非常快(因为它没有创建具有1000个记录的数组)。老实说,我认为在测试代码中可能有一个错误,使得这个版本如此疯狂的快(如果你会发现一些,请告诉我)。无论如何,在真实的应用程序中不太可能有1000个cookie;)
对于具有10个长cookie的真实测试数据集来说,它很慢。
function getCookieIndexOf(name) {
const nameEQ = name + '=';
const cookies = document.cookie;
const cookieStart = cookies.indexOf(nameEQ);
if (cookieStart !== -1) {
const cookieValueStart = cookieStart + nameEQ.length;
const cookieEnd = cookies.indexOf(';', cookieValueStart);
const value = cookies.substring(
cookieValueStart,
cookieEnd !== -1 ? cookieEnd : undefined
);
return decodeURIComponent(value); // returns first found cookie
}
return null;
}
Array.find()版本
function getCookieFind(name) {
const nameEQ = name + '=';
const foundCookie = document.cookie
.split('; ')
.find(c => c.indexOf(nameEQ) === 0); // returns first found cookie
if (foundCookie) {
return decodeURIComponent(foundCookie.substring(nameEQ.length));
}
return null;
}
香草,老派,for循环版本;)
function getCookieFor(name) {
const nameEQ = name + "=";
const ca = cookies.split('; ');
for(let i=0; i < ca.length; i++) {
const c = ca[i];
if (c.indexOf(nameEQ) === 0) {
const value = c.substring(nameEQ.length);
return decodeURIComponent(value); // returns first found cookie
}
}
return null;
}
// ES5 version:
function getCookieFor(name) {
var nameEQ = name + "=";
var ca = cookies.split('; ');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
if (c.indexOf(nameEQ) === 0) {
var value = c.substring(nameEQ.length);
return decodeURIComponent(value); // returns first found cookie
}
}
return null;
}
Array.reduce()版本
我的这个答案从@artnikpro的固定版本-返回第一个找到的cookie,所以工作更好的重复cookie名称为当前路径(例如path=/faq)和path=/。
这个版本是所有性能测试中最慢的版本,因此应该避免使用。
function getCookieReduce(name) {
return document.cookie.split('; ').reduce((r, v) => {
const [n, ...val] = v.split('='); // cookie value can contain "="
if(r) return r; // returns first found cookie
return n === name ? decodeURIComponent(val.join('=')) : r; // returns last found cookie (overwrites)
}, '');
}
您可以在这里自己运行基准测试:https://www.measurethat.net/Benchmarks/Show/16012/5/getcookie-for-vs-forof-vs-indexof-vs-find-vs-reduce
setCookie() TypeScript函数
下面是我使用encodeURIComponent、TypeScript和SameSite选项(Firefox很快就会需要这些选项)设置cookie的函数版本:
function setCookie(
name: string,
value: string = '',
days: number | false = false, // session length if not provided
path: string = '/', // provide an empty string '' to set for current path (managed by a browser)
sameSite: 'none' | 'lax' | 'strict' = 'lax', // required by Firefox
isSecure?: boolean
) {
let expires = '';
if (days) {
const date = new Date(
Date.now() + days * 24 * 60 * 60 * 1000
).toUTCString();
expires = '; expires=' + date;
}
const secure = isSecure || sameSite === 'none' ? `; Secure` : '';
const encodedValue = encodeURIComponent(value);
document.cookie = `${name}=${encodedValue}${expires}; path=${path}; SameSite=${sameSite}${secure}`;
}
谷歌Chrome Cookie存储API
感谢@oncode的回答,值得一提的是谷歌Chrome团队已经提出了一些标准化(终于!这真的很可笑,我们仍然没有任何普遍接受的Cookie API)与异步Cookie存储API(可在谷歌Chrome从版本87开始):https://wicg.github.io/cookie-store/
不幸的是,它仍然是非官方的,甚至不在W3C的考虑范围内,也不在ES的提案范围内:github.com/tc39/proposals
真遗憾,我们仍然没有任何标准的cookie API…
幸运的是,我们为其他浏览器提供了cookie存储polyfill,如npm package (gitHub),它只有1.7kB gzip;)
通过类似sessionStorage和localStorage的接口:
const cookieStorage = {
getItem: (key) {
const cookies = document.cookie.split(';')
.map(cookie => cookie.split('='))
.reduce(
(accumulation, [key, value]) => ({...accumulation, [key.trim()]: value}),
{}
)
return cookies[key]
},
setItem: (key, value) {
document.cookie = `${key}=${value}`
},
}
它的用法cookieStorage。setItem(", ")和cookieStorage.getItem(")。
对于读取简单的查询字符串,这一行代码可能在最新版本的JavaScript中适用:
let cookies = Object.fromEntries(document.cookie.split(';').map(i=>i.trim().split('=')));
现在你有了一个带有键和值的JavaScript对象。
对于创建,你可以试试这个:
let cookieObject = {foo: 'bar', ping: "pong"}
Object.entries(cookieObject).map((e)=>`${e[0]}=${e[1]}`).join(';')
推荐文章
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象
- 使嵌套JavaScript对象平放/不平放的最快方法
- 如何以及为什么'a'['toUpperCase']()在JavaScript工作?
- 有Grunt生成index.html不同的设置
- 文档之间的区别。addEventListener和window。addEventListener?
- 如何检查动态附加的事件监听器是否存在?
- 如何写setTimeout与参数Coffeescript
- 将JavaScript字符串中的多个空格替换为单个空格
- JavaScript: override alert()
- 重置setTimeout
- 如何确保<select>表单字段被禁用时提交?
- jQuery有不聚焦的方法吗?
- 反应钩子-正确的方式清除超时和间隔