首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >轻型Cookiemanager

轻型Cookiemanager
EN

Code Review用户
提问于 2013-03-29 21:31:57
回答 1查看 491关注 0票数 3

我一直在开发一个轻量级的cookiemanager,第1版已经完成,并按照预期完美地工作。我很想得到一份评论,看看我们能在哪里改进它。

我应该在哪里抛出逻辑错误?现在我只写日志。

其用法如下:

可以通过调用Cookiemanger.get()来获取cookie。您可以提供一个name参数来获得特定的cookie,如果没有提供名称,它将返回文档中当前的所有cookie。可以将附加标志设置为第二个参数,是否对cookie名称使用严格匹配。

代码语言:javascript
复制
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。它需要至少提供一个名称键/值的设置对象。

代码语言:javascript
复制
// 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个参数:namedomainpath作为字符串。domainpath是可选的。如果没有提供,它将从域中删除所有cookie,包括所有子路径。

代码语言:javascript
复制
// 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,如下所示。

代码语言:javascript
复制
Cookiemanger.test({
    name : 'testcookie',
    'an_expected_value' : function () {
    },
    'undefined' : function () {
    }
});
代码语言:javascript
复制
;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));
EN

回答 1

Code Review用户

回答已采纳

发布于 2013-03-30 17:23:40

对于一个“轻量级”的cookie管理器来说,在我看来似乎有很多事情要做。我称对象为CookieManager,因为它是两个单词,但这在结构/语法上并不重要。

不过,我对get()的使用有点怀疑。如果我给它一个字符串,没有其他的,我希望它做严格的名称匹配。也就是说,给一个名字,我期望零或一个cookie作为回报,而不是一个列表。可能将“模糊匹配”分解为find()方法,或者让get()接受正则表达式。

说到正则表达式,这可能是解析document.cookie字符串的最简单方法:

代码语言:javascript
复制
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,并且基本上成为一个非常简单的快捷方式。

代码语言:javascript
复制
function get(name) {
  return all()[name];
}

我不会费心在cookie管理器中记录错误,因为您仍然需要在其他地方检查返回值。在这种情况下,get()只返回一个字符串值或未定义的字符串值。垃圾进入,垃圾输出。

现在,对于模糊名称匹配,我要添加一个find()函数,以区别于更严格的get()函数。有点像

代码语言:javascript
复制
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方法,因为他们不返回一些东西。所以这更像是“垃圾进来,抛出异常”

同样,尝试日志的理由也不多,只是为了冒在那里抛出异常的风险;如果输入是假的,可能更容易抛出。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/24513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档