我一直在开发一个轻量级的cookiemanager,第1版已经完成,并按照预期完美地工作。我很想得到一份评论,看看我们能在哪里改进它。
我应该在哪里抛出逻辑错误?现在我只写日志。
其用法如下:
可以通过调用Cookiemanger.get()来获取cookie。您可以提供一个name参数来获得特定的cookie,如果没有提供名称,它将返回文档中当前的所有cookie。可以将附加标志设置为第二个参数,是否对cookie名称使用严格匹配。
Cookiemanager.get(); // returns all cookies currently defined in the document as a name/value object.
Cookiemanager.get('your_cookie_name'); // returns cookie(s) as a name/value object, using loose matching. so 'your_cookie_name_123' will get returned also.
Cookiemanager.get('your_cookie_name', true); // Same as above only now it will do strict name matching.可以通过调用Cookiemanger.set()来设置cookie。它需要至少提供一个名称键/值的设置对象。
// Simple setting
Cookiemanger.set({
name : 'your_cookie_name',
value : 'your value'
});
// Extended setting
Cookiemanger.set({
name : 'your_cookie_name',
value : 'your value',
expires : 'a expiry date in as a UTC string'
path : '/',
domain : document.location.host,
secure : false
});删除cookie可以通过调用Cookiemager.remove()来完成。它接受3个参数:name、domain和path作为字符串。domain和path是可选的。如果没有提供,它将从域中删除所有cookie,包括所有子路径。
// Removes the cookie at the current domain, including all sub paths.
Cookiemanger.remove({
name : 'your_cookie_name',
domain : document.location.host
});
// Removes the cookie at the supplied path, excluding sub paths.
Cookiemanger.remove({
name : 'your_cookie_name',
path: '/'
});可以通过调用Cookiemanger.test()来测试某个值的cookie。它接受设置对象,如下所示,至少提供了一个名称。如果一个值与当前cookie中的值匹配,则可以添加自定义值,如果提供,它将调用该函数。如果没有找到具有所提供名称的cookie,则可以传递一个未定义的cookie,如下所示。
Cookiemanger.test({
name : 'testcookie',
'an_expected_value' : function () {
},
'undefined' : function () {
}
});;var Cookiemanager = (function (Cookiemanager, window, document, undefined) {
'use strict';
function isObject (arg) {
return Object.prototype.toString.call(arg) === '[object Object]';
};
function isArray (arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
function isString (arg) {
return Object.prototype.toString.call(arg) === '[object String]';
};
function isEmptyObj (argument){
for( var key in argument ) return false;
return true;
};
function returnCookieString (sName, sValue, sExpires, sPath, sDomain, bSecure) {
var sCookie = (sName + '=' + escape(typeof sValue !== 'undefined' ? sValue : '')) +
(isString(sExpires) && sExpires.indexOf('GMT') !== -1 ? ';expires=' + sExpires : '') +
(isString(sPath) ? ';path=' + sPath : ';path=') +
(isString(sDomain) ? ';domain=' + sDomain : '') +
(bSecure ? ';secure' : '');
return sCookie;
};
function returnURIPaths () {
var i,
sURIPath,
aURIPaths = [],
aURISegments = document.location.pathname.replace(/\/$/, '').split('/'),
iNrOfURISegments = aURISegments.length;
for (i = iNrOfURISegments; i--;) {
sURIPath = aURISegments.slice(0, i + 1).join('/');
aURIPaths.push(sURIPath);
aURIPaths.push(sURIPath + '/');
}
return aURIPaths;
};
function error (msg) {
throw new Error(msg);
};
function log (msg) {
try {
console.log(msg);
} catch (e) {}
};
Cookiemanager.get = function (arg, strict) {
var sCookies = document.cookie;
if (sCookies.length) {
var i,
oResult = {},
aCookies = sCookies.split(';'),
iNrOfCookies = aCookies.length,
sCookie,
aCookieValues,
sCookieName,
sCookieValue;
for (i = iNrOfCookies; i--;) {
sCookie = aCookies[i];
if (sCookie.charAt(0) === ' ') {
sCookie = sCookie.substring(1, sCookie.length);
}
aCookieValues = sCookie.split('=');
sCookieName = aCookieValues[0];
sCookieValue = unescape(aCookieValues[1]);
if (arg && isString(arg)) {
if (strict) {
if (sCookieName === arg) {
oResult[sCookieName] = sCookieValue;
}
} else {
if (sCookieName.indexOf(arg) !== -1) {
oResult[sCookieName] = sCookieValue;
}
}
} else {
oResult[sCookieName] = sCookieValue;
}
}
if (! isEmptyObj(oResult)) {
return oResult;
} else {
log('Cookiemanager.get(): Could not find cookie with supplied name.');
}
} else {
log('Cookiemanager.get(): No cookies defined in the current document.');
}
};
Cookiemanager.set = function (arg) {
if (arg && isObject(arg)) {
if (isString(arg.name)) {
document.cookie = returnCookieString(arg.name, arg.value, arg.expires, arg.path, arg.domain, arg.secure);
} else {
log('Cookiemanager.set(): Cookie not set, please provide a valid name.');
}
} else {
log('Cookiemanager.set(): Cookie not set, please provide a valid settings object.');
}
};
Cookiemanager.remove = function (sName, sPath, sDomain) {
if (isString(sName)) {
var expires = new Date();
expires.setFullYear(expires.getFullYear() - 1);
if (isString(sPath)) {
this.set({
name : sName,
expires : expires.toUTCString(),
path : sPath,
domain : typeof sDomain !== 'undefined' ? sDomain : document.location.host
});
} else {
var i,
aURIPaths = returnURIPaths(),
iNrOfURIPaths = aURIPaths.length;
for (i = iNrOfURIPaths; i--;) {
this.set({
name : sName,
expires : expires.toUTCString(),
path : aURIPaths[i],
domain : typeof sDomain !== 'undefined' ? sDomain : document.location.host
});
}
}
} else {
log('Cookiemanager.remove(): No cookies removed, please provide a valid name.');
}
};
Cookiemanager.test = function (arg, strict) {
if (arg && isObject(arg)) {
var sName = arg.name;
if (isString(sName)) {
var oCookie = this.get(sName, strict || false);
if (isEmptyObj(oCookie)) {
arg['undefined'].call(this);
} else {
for(var key in arg) {
if (key === oCookie[sName]) {
arg[key].call(this);
}
}
}
} else {
log('Cookiemanager.test(): Could not test, please provide a valid name.');
}
} else {
log('Cookiemanager.test(): Could not test, please provide a valid settings object.');
}
};
return Cookiemanager;
}(Cookiemanager || {}, this, this.document));发布于 2013-03-30 17:23:40
对于一个“轻量级”的cookie管理器来说,在我看来似乎有很多事情要做。我称对象为CookieManager,因为它是两个单词,但这在结构/语法上并不重要。
不过,我对get()的使用有点怀疑。如果我给它一个字符串,没有其他的,我希望它做严格的名称匹配。也就是说,给一个名字,我期望零或一个cookie作为回报,而不是一个列表。可能将“模糊匹配”分解为find()方法,或者让get()接受正则表达式。
说到正则表达式,这可能是解析document.cookie字符串的最简单方法:
function all() {
var cookies = {};
// using replace, as it accepts a function
document.cookie.replace(/([^=]+)=([^;]*)[;\s]*/g, function(match, name, value) {
cookies[name] = value;
});
return cookies;
}这将为您提供所有cookie的对象(或哈希或映射(如果您愿意)。您还可以将其公开为CookieManager.all(),而不是用另一种用法重载get()方法。
在内部,get()可以使用all()获取单个cookie,并且基本上成为一个非常简单的快捷方式。
function get(name) {
return all()[name];
}我不会费心在cookie管理器中记录错误,因为您仍然需要在其他地方检查返回值。在这种情况下,get()只返回一个字符串值或未定义的字符串值。垃圾进入,垃圾输出。
现在,对于模糊名称匹配,我要添加一个find()函数,以区别于更严格的get()函数。有点像
function find(pattern) {
var name,
found = {},
cookies = all();
if( pattern instanceof RegExp ) {
for( name in cookies ) {
if( pattern.test(name) ) {
found[name] = cookies[name];
}
}
} else {
for( name in cookies ) {
if( name.indexOf(pattern) !== -1 ) {
found[name] = cookies[name];
}
}
}
return found;
}再一次,GIGO。不一定是你有责任检查这些论点。
最后,我可能会让set()接受特定的参数,而不是一个对象,因为它使它的用法更加明显。如果我只需要传递一个对象,我仍然必须知道该对象应该包含什么。
另一个原因是使其与remove()函数保持一致,该函数已经使用了特定的参数。
set()和remove()是两个函数,可能需要进行一些输入检查,并可能抛出异常。这主要是因为他们不能真正遵循GIGO方法,因为他们不返回一些东西。所以这更像是“垃圾进来,抛出异常”
同样,尝试日志的理由也不多,只是为了冒在那里抛出异常的风险;如果输入是假的,可能更容易抛出。
https://codereview.stackexchange.com/questions/24513
复制相似问题