mojs,一个javascript常用方法库,包含了浏览器中对storage、cookie的操作封装,e5 super,date日期处理,身份证、url中元素校验解析,及一些其他常用的方法集合(正则、extend、继承、类等...)。

源码采用AMD书写,以webpack打包,karma+jasmine单元测试,UMD格式输出。

common

一些底层的方法

var foo, obj1, obj2, obj3;

function Foo () {
  this.a = 1
};
Foo.prototype.b = 2;
foo = new Foo();

obj1 = {
  a: 1,
  b: 2,
  toString: 3,
  isPrototypeOf: 4,
  constructor: 5
};
obj2 = {
  b: 22,
  c: {
    d: 6
  }
};
obj3 = {
  c: {
    e: 7,
    f: {
      g: 8,
      h: 9
    }
  }
};

hasc.has(obj, key)
判断是否是非继承属性

c.has(foo, 'a') => true
c.has(foo, 'b') => false

forInc.forIn(obj, iteratee[, context])
兼容 IE8- 下有些不枚举的属性,例如'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'

@param {object} obj
@param {function} iteratee
  - param {..} value
  - param {..} key
  - param {object} forIn的第一个参数obj
@param {object} iteratee的上下文,可选
c.forIn(obj1, function(v, k) {
  console.log(k + ':' + v)
})
=> 依次输出: 'a: 1', 'b: 2', 'toString: 3', 'isPrototypeOf: 4', 'constructor: 5'

extendc.extend([isDeep,] obj1, obj2, obj3...)
合并对象到第一个obj

@param {boolean} 是否深度复制,可选
@param {object|array} 目标对象
@params {object|array} 需要extend的对象,可多个参数
@return {object|array} extend后的object
c.extend(obj1, obj2) => {a: 1, b: 22, c: {d: 6}, toString: 3, isPrototypeOf: 4, constructor: 5}
// 浅拷贝
c.extend(obj2, obj3) => {b: 22, c: {e: 7, f: {g: 8, h: 9}}}
// 深度拷贝
c.extend(true, obj1, obj2, obj3)
=> {a: 1, b: 22, c: {d: 6, e: 7, f: {g: 8, h: 9}}, toString: 3, isPrototypeOf: 4, constructor: 5}

typec.type()
判断对象的类型

c.type({a: 1}) => 'object'
c.type('mojs') => 'string'
c.type(2) => 'number'

isBooleanc.isBoolean()
是否是Boolean类型

c.isBoolean({a: 1}) => false

isNumberc.isNumber()
是否是Number类型

isStringc.isString()
是否是String类型

isFunctionc.isFunction()
是否是Function类型

isDatec.isDate()
是否是Date类型

isRegExpc.isRegExp()
是否是RegExp类型

isObjectc.isObject()
是否是Object类型

isArrayc.isArray()
是否是数组

isArraylikec.isArraylike()
是否是类数组, 例如nodelist,arguments,具有length并且keys为0.1.2...的obj

c.isArraylike([1, 2, 3]) => true
c.isArraylike({1: 1, 2: 2, 3: 3, length: 3}) => true
c.isArraylike({1: 1, 2: 2, 3: 3}) => false

isNaNc.isNaN()
判断是否为NaN

c.isNaN(NaN) => true
c.isNaN(undefined) => false

sizec.size(obj)
返回obj的长度

c.size([1, 2, 3]) => 3
c.size({a: 1, b: 2}) => 2

trimc.trim(text)
去掉字符串前后的空

c.trim(' abc defg ') => 'abc defg'

keysc.keys(obj)
获取对象的key集合

c.keys({a: 1, b: 2}) => ['a', 'b']

nowc.now()
当前时间戳

logc.log()
同console.log()

baseCreatec.baseCreate(prototype)
同Object.create(prototype)

@param {object} prototype
@return {object} 原型为参数prototype的对象
c.baseCreate() => {}
c.baseCreate({ a: Foo }).a => Foo

baseClassc.baseClass(subCtor, prototypes, superCtor)
创建一个构造函数(继承、原型方法都可选,继承可以通过新构造函数的superCtor访问父级构造函数)

@param {function} (子级)构造函数
@param {object} 原型的方法集,可选
@param {function} 父级构造函数,可选
@return {function} 新的构造函数
c.baseClass(A, {a: function() {}, b: function(){}}, B) => A继承B,并且prototype上添加方法a和b
c.baseClass(A, {a: function() {}, b: function(){}}) => A的prototype上添加方法a和b
c.baseClass(A, B) => A继承B

操作cookie的方法

@param {object} options
  - isRaw {boolean} 是否原生字符(不转码), 默认为false
  - isJson {boolean} 是否str->json, 默认为false
var
  cookie = new Cookie(),
  cookie2 = new Cookie({isRaw: true, isJson: true});
@param {string} name
@param {..} value
@param {obj} options
  - expires {number|string} 失效时长,单位 ‘天’, 默认为Session
  - path    {string} 路径,path只能设置当前path的子path, 默认为当前path
  - domain  {string} 域,domain只能设置当前domain的子domain, 默认为当前domain
  - secure  {boolean} 安全策略,只有https下能设置 ture or false, 默认为false
cookie.set('user', 'mo');
cookie2.set('user2', {a: 'mojs', b: 'modoc'}, {expires: 1});
@param {string} cookie的name
@return {..} cookie的value
cookie.get('user') => 'mo'
cookie2.get('user2') => {a: 'mojs', b: 'modoc'}
@param {string} cookie的name
cookie.remove('user')

date

日期格式化、计算

var
  birthday = new Date(), // 默认值,当前客户端时间Date实例
  birthday2 = '/Date(562941040500+0800)/', // 非JS格式的时间戳,例如.NET
  birthday3 = '1987/11/03 20:30:40', // 需要重新格式化的字符串,注意12小时制不支持
  birthday4 = '1987/11/03', // 需要重新格式化的字符串
  birthday5 = 562941040500, // 时间戳(number/string)
  birthday6 = new Date('1987', '10', '03', '20', '30', '40', '500'); // Date实例

formatdate.format([date,] format)
格式化日期

@param {number/string/date} 需要格式化的date
@param {string} token字符串
@return {string} 格式化后的字符串
date.format(birthday6, 'YYYY-MM-DD HH:mm:ss:SSS') => '1987-11-03 20:30:40:500'
date.format(birthday6, 'YY年M月D日 h时m分s秒 S毫秒 ddd') => '87年11月3日 8时30分40秒 500毫秒 周二'
date.format(birthday6, '\\Q\\ww\\a,第Q季度,第ww周季度,A') => 'Qwwa,第4季度,第45周季度,PM'
token映射表 参照 http://momentjs.com/docs/#/displaying/,只引用了其中一部分,涉及到中文的部分稍微有调整
==================================================================
                         Token       Output
Month                    M           1 2 ... 11 12
                         MM          01 02 ... 11 12
Quarter                  Q           1 2 3 4
Day of Month             D           1 2 ... 30 31
                         DD          01 02 ... 30 31
Day of Year              DDD         1 2 ... 364 365
                         DDDD        001 002 ... 364 365
Day of Week              d           0 1 ... 5 6
                         ddd         周日 周一 ... 周五 周六
                         dddd        星期日 星期一 ... 星期五 星晴六
Week of Year             w           1 2 ... 52 53
                         ww          01 02 ... 52 53
Year                     YY          70 71 ... 29 30
                         YYYY        1970 1971 ... 2029 2030
AM/PM                    A           AM PM
                         a           am pm
                         aa          上午 下午
Hour                     H           0 1 ... 22 23
                         HH          00 01 ... 22 23
                         h           1 2 ... 11 12
                         hh          01 02 ... 11 12
Minute                   m           0 1 ... 58 59
                         mm          00 01 ... 58 59
Second                   s           0 1 ... 58 59
                         ss          00 01 ... 58 59
Fractional Second        S           0 1 ... 8 9
                         SS          0 1 ... 98 99
                         SSS         0 1 ... 998 999
==================================================================

add/subdate.add([date,] name, number)/date.sub([date,] name, number)
日期加减计算

@param {number|string|date} 需要格式化的date,不传默认为当前时间
@param {string} 单位['FullYear', 'Month', 'Date', 'Hours', 'Minutes', 'Seconds', 'Milliseconds', 'Time']
@param {number} n单位
@return {Date} 计算后的结果
date.add(birthday6, 'Hours', 1) => Tue Nov 03 1987 21:30:40 GMT+0800 (CST)
date.sub(birthday6, 'Minutes', 1) => Tue Nov 03 1987 20:29:40 GMT+0800 (CST)

es5

es5 super 其中each,map,filter,some,every可以应用到类数组,对象 indexOf,lastIndexOf,reduce,reduceRight可以应用到类数组

eaches5.each(obj, iteratee[, context])
遍历类数组或者对象,如果想终止循环return false即可

@param {arraylike|object} 类数组或者对象
@param {function} 迭代函数
  - param {..} value
  - param {..} index|key
  - param {array|object} each的第一个参数
@param {object} iteratee的上下文,可选

mapes5.map(obj, iteratee[, context])
遍历类数组或者对象,返回一个新数组(obj执行iteratee后的返回值的集合)

@param {arraylike|object} 类数组或者对象
@param {function} 迭代函数
  - param {..} value
  - param {..} index/key
  - param {array|object} map的第一个参数
@param {object} iteratee的上下文,可选
@return {array} 结果

filter
遍历类数组或者对象,返回一个新数组(obj执行iteratee后返回值为真的value的元素的集合),其他同map

some
遍历类数组或者对象,obj执行iteratee后返回值如果有一个为真,则返回true,否则返回false,其他同map

every
遍历类数组或者对象,obj执行iteratee后返回值如果全为真,则返回true,否则返回false,其他同map

indexOfes5.indexOf(array, item[, from])
返回item在arraylike中的索引值(从0开始找),如果item不存在arraylike中就返回-1,原生不支持NaN

@param {arraylike} 需要查找的类数组
@param {..} 需要查找的元素
@param {number} 开始索引,可选
@return {number} 查找到元素的索引值

lastIndexOf
同indexOf,区别是从arraylike的末尾开始(从右到左)

bindes5.bind(func, context[, arg1] [, arg2...])
函数绑定

@param {function} 需要绑定上下文或者是添加参数的函数
@param {object} func的上下文
@params {..} 需要添加的n个参数
@return {function} 绑定上下文或者是添加参数后函数

reducees5.reduce(arraylike, iteratee[, memo][, context])
接收一个函数作为累加器,类数组中的每个值从左到右开始缩减,最终为一个值

@param {arraylike} 类数组
@param {function} 迭代函数
  - param {..} previousValue
  - param {..} currentValue
  - param {..} index/key
  - param {array|object} reduce的第一个参数
@param {..} 可选,作为第一次调用iteratee的第一个参数,如果不存在,则把第一次要iteratee的value复制给memo,并且跳过index这次iteratee
@param {object} iteratee的上下文,可选

reduceRight
同reduce,区别是从类数组的末尾开始(从右到左)

IdCard

身份证的校验以及从从身份证号码中获取一些信息,例如出生日期,性别

身份证规则
=====================================================================
身份证15位编码规则 -- dddddd yymmdd xx p
dddddd : 地区码
yymmdd : 出生年月日
xx     : 顺序类编码,无法确定
p      : 性别,奇数为男,偶数为女

身份证18位编码规则 -- dddddd yyyymmdd xxx y
dddddd   : 地区码
yyyymmdd : 出生年月日
xxx      : 顺序类编码,无法确定,奇数为男,偶数为女
y        : 校验码,该位数值可通过前17位计算获得

18位号码加权因子为          : WI = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1]
校验位集合                  : CODE = [1, 0, 'x', 9, 8, 7, 6, 5, 4, 3, 2]
校验位index计算公式         : index = mod(∑(ai×Wi), 11)
=====================================================================

IdCardnew IdCard(num)
构造函数

@param {string} 身份证号,这里必须是string格式,因为身份证号超出了js的整数精度范围
var idCard = new IdCard('610125198711037137');

checkCode
验证校验位,针对18位

@return {boolean} 
idCard.checkCode() => true

checkBirth
验证出生日期

@return {boolean} 
idCard.checkBirth() => true

getBirth
获取出生日期

@return {object} 返回对象
  - year  {number}
  - month {number}
  - day   {number}
idCard.getBirth() => {year: '1987', month: '11', day: '03'}

getSex
获取性别

@return {string} 
idCard.getSex() => '男'

objectPath

读取或设置object path下的value

var obj = { f: { g: 'blog' } };

setobjectPath.set(obj, path, value)
设置object path下的value

@param {object} obj
@param {string} path
@param {..} value
@return {boolean} 成功true,失败false
objectPath.set(obj, 'a.d', 'mojs') => obj.a.d = 'mojs'
objectPath.set(obj, 'a.b.e', 'modoc') => obj.a.b.e = 'modoc'

getobjectPath.set(obj, path)
读取object path下的value

@param {object} obj
@param {string} path
@return {..} value
objectPath.get(obj, 'f.g') => 'blog'
objectPath.get(obj, 'a.b.e') => 'mojs'

ParseUrl

解析url

url注解
=====================================================================

http://username:password@www.example.com:80/path/file.name?query=string#anchor
|__|   |______| |______| |_____________||_||___||________||___________||_____|
 |        |        |            |       |   |         |         |        |
protocol user   password      host  port directory  file      query   anchor
      |_______________|                   |_____________|
              |                                 |
           userInfo                           path
     |___________________________________||_________________________________|
                       |                                   |
                   authority                          relative
|___________________________________________________________________________|
                                        |
                                      source

=====================================================================

ParseUrlnew ParseUrl(url)
构造函数

@param {string} 默认为location.href
var parseUrl = new ParseUrl('http://username:password@www.example.com:80/path/file.name?query=string#anchor');

getAttrparseUrl.getAttr([name])
读取url中的attr,name为空,则返回所有attr

@param {string} name,可选 范围"source", "protocol", "authority", "userInfo", "user",
"password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"
@return {string} value
parseUrl.getAttr('port') => '80'
url.getAttr('protocol') => 'http'

getParamparseUrl.getParam([name])
读取url中的param,name为空,则返回所有param

@param {string} name
@return {string} value
parseUrl.getParam() => {query: 'string'}
parseUrl.getParam('query') => 'string'

pubSub

pub/sub 发布订阅

var
  data = [{
    name: '熊大',
    job: '阻止光头强砍树'
  }, {
    name: '熊二',
    job: '调戏光头强'
  }, {
    name: '光头强',
    job: '伐木'
  }],
  handler = handler = function(data) {
    console.log(data.name + '应该' + data.job);
  },
  handler2 = function(data) {
    console.log(data.name + '喜欢' + data.job);
  };

publishpubSub.publish(message, data)
发布

@param {string} 消息,支持子message. eg. 'a.b.c'
@param {..} 执行订阅的handler时传入的data

subscribepubSub.subscribe(message, handler[, context])
订阅(注意,message不要包含'id_', eg. '...id_...')

@param {string} 消息
@param {function} 处理句柄
@param {object} handler执行的上下文,可选
pubSub.subscribe('a', handler);
pubSub.subscribe('a', handler2);
pubSub.publish('a', data[0]);
=> '熊大应该阻止光头强砍树'
=> '熊大喜欢阻止光头强砍树'
pubSub.subscribe('b', handler);
pubSub.subscribe('b.b', handler2);
pubSub.publish('b', data[1]);
=> '熊二应该调戏光头强'
=> '熊二喜欢调戏光头强'
pubSub.subscribe('c', handler);
pubSub.publish('c', data[2]);
=> '光头强应该伐木'

unsubscribepubSub.unsubscribe(message, handler)
取消订阅(只能取消此message上的handler,不能作用于子message)

@param {string} 消息
@param {function} 处理句柄,可选,如果为空则清除message上的所有handler
pubSub.unsubscribe('a', handler2);
pubSub.publish('a', data[0]);
=> '熊大应该阻止光头强砍树'
pubSub.unsubscribe('b');
pubSub.publish('b', data[1]);
=> '熊二喜欢调戏光头强'

clearpubSub.unsubscribe(message)
清除某个message(包含子message)或者所有message的订阅

@param {string} 消息,可选,如果message为空,则清除所有message.
pubSub.clear('b');
pubSub.publish('b', data[1]);
pubSub.clear();
pubSub.publish('c', data[2]);

rules

常用的正则校验规则

// 校验,返回值为true/false
rules.isRequired('校验文本') // 必填
rules.isChinese(..) // 中文
rules.isDoubleByte(..) // 双字节
rules.isZipcode(..) // 邮政编码
rules.isQq(..) // QQ
rules.isPicture(..) // 图片
rules.isRar(..) // 压缩文件
rules.isMobile(..) // 手机号
rules.isMoney(..) // 金额(不能包含分隔符)
rules.isEnglish(..) // 英文字母
rules.isLowerCase(..) // 英文小写
rules.isUpperCase(..) // 英文大写
rules.isNumber(..) // 纯数字
rules.isInteger(..) // 整数
rules.isFloat(..) // 浮点数
rules.isRealName(..) // 姓名(中英文)
rules.isEmail(..) // 邮箱
rules.isUrl(..) // 网址 http://mhbsesal.com
rules.isIdCard(..) // 身份证
rules.isPhone(..) // 座机(区号-主号-分机号)029-8784326-11316
rules.isAreaNum(..) // 座机-区号
rules.isHostNum(..) // 座机-主号
rules.isExtensionNum(..) // 座机-分机号
rules.isIp(..) // IP地址

AbstractStore

store的抽象类,针对storage中的key,一般不使用该类,常用他的子类LocalStore(options.storage = window.localStorage)、SessionStore(options.storage = window.sessionStorage)

AbstractStorenew AbstractStore(options)
构造函数

@param {object} options
  - proxy           {AbstractStorage} AbstractStorage实例
  - key             {string} key
  - lifetime        {string} 生命周期,默认'1H' 单位D,H,M,S. eg. '24H'
  - rollbackEnabled {boolean} 是否回滚
var store = new AbstractStore({
  proxy: new AbstractStorage({
    storage: window.localStorage
  })
  key: 'USER'
}))

setstore.set(value[, tag][, isOld])
设置this.key下的value

@param {..} value
@param {string} 可选,tag标识,如果传递tag,get时会比较tag标识,不一致返回null
@param {string} 可选,默认false,是否设置回滚数据
@return {boolean} 成功true,失败false

setAttrstore.setAttr(name, value[, tag][, isOld])
设置this.key下的value中name的value

@param {String} name 支持通过路径的方式,如'a.b.c'
@param {..} value
@param {string} 可选,tag标识,如果传递tag,get时会比较tag标识,不一致返回null
@param {string} 可选,默认false,是否设置回滚数据
@return {boolean} 成功true,失败false

getstore.get([tag][, isOld])
读取this.key下的value

@param {string} 可选,tag标识,如果传递tag,get时会比较tag标识,不一致返回null
@param {string} 可选,默认false,是否设置回滚数据
@return {..} value

getAttrstore.getAttr(name[, tag][, isOld])
读取this.key下的value中name的value

@param {String} name 支持通过路径的方式,如'a.b.c'
@param {string} 可选,tag标识,如果传递tag,get时会比较tag标识,不一致返回null
@param {string} 可选,默认false,是否设置回滚数据
@return {..} value

getTagstore.getTag()
获取tag

removestore.remove()
移除存储对象

setExpireTimestore.setExpireTime()
设置失效时间

@param {number} timeout

getExpireTimestore.getExpireTime()
返回失效时间

rollbackstore.rollback([isClearOld])
回滚至上个版本

@param {string} 可选,默认false,回滚后是否清除回滚数据
@return {boolean} 成功true,失败false

LocalStore

AbstractStore的子类

var store = new AbstractStore({
  key: 'USER'
})

SessionStore

AbstractStore的子类

var store = new AbstractStore({
  key: 'USER'
})

utils

工具方法集

guidutil.guid()
生成guid

@return {string} guid
util.guid() => 'd42fb5af-9b78-6320-9a79-327cb00ea561'

getByteInfoutil.getByteInfo(str[, index])
字符串的长度和index计算

@param {string} 要计算的字符串
@param {number} 可选,字符串(双字节长度为2)的index
@return {object} 返回对象
  - length {number} 字符串(双字节长度为2)的长度
  - index  {number} 字符串的index,如果参数index为空,则该字段无返回值
util.getByteInfo('我的生日是1987年11月03日', 5) => Object {length: 24, index: 2}
util.getByteInfo('生日:1987-08-05') => Object {length: 16}

padutil.pad(str, len[, fill][, right])
字符串填充

@param {string} 需要处理的字符串,非字符串会先转换为字符串
@param {number} 填充的长度,如果需要处理的字符串大于此参数,则放弃
@param {string} 可选,填充字符,非字符串会先转换为字符串,默认为空格字符
@param {boolean} 可选,左边还是右边,默认为false,左边
@param {boolean} 可选,字符串的长度超过参数len是否截取,默认为false
@return {string} 处理后的字符串
util.pad('mo', 4, '-') => '--mo'
util.pad(19871103, 14, 0, true) => '19871103000000'
util.pad(19871103, 6, null, false, true) => '871103'