jbd
Version:
jBD Framework's Core
2,018 lines (1,769 loc) • 77.1 kB
JavaScript
"use strict";
(function (global, factory) {
if (global.jBD) return;
factory.call(
{ver: "2.2.32"},
global,
{
Node: 0,
Web: 0xff,
WebDesktop: 0x0f,
WebMac: 0x08,
WebMobile: 0xf0,
WebiPhone: 0x10,
WebiPad: 0x20,
WebAndroid: 0xc0,
WebAPhone: 0x40,
WebAPad: 0x80
});
})(typeof (window) !== "undefined" ? window : global, function (global, MODE) {
const jBD = this;
if (!global.navigator) global.navigator = {userAgent: ""};
global.jBD = jBD;
jBD.MODE = MODE;
jBD.mode = MODE.Node;
/**
* 环境判断
*
* @param {string} [na=undefined] 版本字符串
* @returns {object}
* @return {number} mode 模式,对应MODE码表
* @return {string} kernel 内核名称
* @return {string} version 内核版本
*/
jBD.version = na => {
let r = {mode: MODE.Node, kernel: "node", version: ""};
if (!na && typeof(window) == "undefined" && process) {
r.kernel = "node";
r.version = process.versions.node;
}
else {
na = typeof(na) == "string" && na ? na : navigator.userAgent;
let s = na.toLowerCase(),
t;
if (t = s.match(/msie ([\d.]+)/)) {
r.kernel = "ie";
r.version = t[1];
}
else if (t = s.match(/firefox\/([\d.]+)/)) {
r.kernel = "firefox";
r.version = t[1];
}
else if (t = s.match(/chrome\/([\d.]+)/)) {
r.kernel = "chrome";
r.version = t[1];
}
else if (t = s.match(/opera.([\d.]+)/)) {
r.kernel = "opera";
r.version = t[1];
}
else if (t = s.match(/version\/([\d.]+).*safari/)) {
r.kernel = "safari";
r.version = t[1];
}
else {
r.kernel = "other";
r.version = "0";
}
if (na.indexOf("Android") > -1 || na.indexOf("Linux") > -1) r.mode = MODE.WebAndroid;
else if (na.indexOf("iPhone") > -1) r.mode = MODE.WebiPhone;
else if (na.indexOf("iPad") > -1) r.mode = MODE.WebiPad;
else if (na.match(/\(i[^;]+;( U;)? CPU.+Mac OS/)) r.mode = MODE.WebMac;
else r.mode = MODE.WebDesktop;
}
return r;
};
jBD.mode = jBD.version().mode;
if (jBD.mode == MODE.Node) exports = module.exports = jBD;
else if (!global.global) global.global = global;
/**
* ==========================================
* Name: jBD‘s Tools
* Author: Buddy-Deus
* CreTime: 2014-12-15
* Description: BD's Tools for JavaScript
* Log:
* 2014-12-15 初始化工具箱
* 2016-09-22 ES6 Format
* 2017-02-10 去除函数默认参数,增加适配
* ==========================================
*/
(jBD => {
/**
* 对象类型识别
*
* @method type
* @param {object} obj 检测对象
* @param {boolean} [detail=false] 是否深度识别
* @returns {string}
* True: boolean, number, string, function, null
* False: boolean, number, string, function, undefined, null, object, arguments, array, date, regexp
*/
jBD.type = (obj, detail) => {
detail = detail === true;
let type = typeof obj;
switch (type) {
default:
case "undefined":
return detail ? "undefined" : "null";
case "boolean":
case "number":
case "string":
case "function":
return type;
case "object":
if (obj === null) return "null";
if (!detail) return "object";
if (obj.jquery) return "jquery";
if (obj instanceof Array) return "array";
if (obj instanceof RegExp) return "regexp";
type = (/^\[object (.*)\]$/.exec(Object.prototype.toString.call(obj))[1]).toLowerCase();
if (type.indexOf("html") == 0) return "dom";
return type;
}
};
/**
* 是否相等
*
* @param {*} a 判断值
* @param {*} b 判断值
* @param {boolean} [abs=true] 判断引用是否相等
* @returns {boolean}
*/
jBD.is = (a, b, abs) => {
if (abs !== false) return Object.is(a, b);
else {
let type = [jBD.type(a, true), jBD.type(b, true)];
if (type[0] != type[1]) return false;
switch (type[0]) {
default:
return Object.is(a, b);
case "function":
return a.toString() == b.toString();
case "date":
return a.getTime() == b.getTime();
case "array":
case "arguments":
case "object":
if (Object.keys(a).length != Object.keys(b).length) return false;
for (let k in a) if (!Object.is(a[k], b[k])) return false;
return true;
}
}
};
/**
* 是否是简单类型
*
* @param value
* @returns {boolean}
*/
jBD.isSimple = value => {
switch (typeof(value)) {
default:
return value === null;
case "undefined":
case "boolean":
case "number":
case "string":
return true;
}
};
/**
* 是否为Null
*
* @param {*} value 判断值
* @param {boolean|object} opt 参数
* @param {boolean} [opt.udf=true] undefined是否为null
* @param {boolean} [opt.obj=false] 数组/对象为空是否为null
* @returns {boolean}
*/
jBD.isNull = (value, opt) => {
let udf, obj;
switch (typeof(opt)) {
case "object":
if (opt) {
udf = opt.udf;
obj = opt.obj;
}
break;
case "boolean":
udf = opt;
break;
}
udf = udf !== false;
obj = obj === true;
switch (typeof(value)) {
default:
return false;
case "undefined":
return udf;
case "object":
if (value === null) return true;
if (!obj) return false;
return Object.keys(value).length == 0;
}
};
/**
* 是否为Boolean
*
* @param {*} value 判断值
* @param {boolean} [str=false] 是否判断字符串
* @returns {boolean}
*/
jBD.isBool = (value, str) => {
return (typeof(value) == "boolean") || (str === true ? (String(value) in {
"true": 1,
"false": 1
}) : false);
};
/**
* 是否为Number
*
* @param {*} value 判断值
* @param {boolean|object} opt 参数
* @param {boolean} [opt.nan=false] NaN是否为数字
* @param {boolean} [opt.str=false] 是否识别字符串
* @param {boolean} [opt.int=false] 是否只识别整数
* @param {number} [opt.min=NaN] 最小值
* @param {number} [opt.max=NaN] 最大值
* @returns {boolean}
*/
jBD.isNumber = (value, opt) => {
let nan, str, int, min, max, func;
switch (typeof(opt)) {
case "object":
if (opt) {
nan = opt.nan;
str = opt.str;
int = opt.int;
min = opt.min;
max = opt.max;
}
break;
case "boolean":
nan = opt;
break;
}
min = Number(min);
max = Number(max);
nan = nan === true;
str = str === true;
if (int = int === true) {
if (!isNaN(min)) min = parseInt(min);
if (!isNaN(max)) max = parseInt(max);
func = v => {
if (parseInt(v) !== v) return false;
if (!isNaN(min) && v < min) return false;
if (!isNaN(max) && v > max) return false;
return true;
}
}
else {
func = (v, b) => {
if (!b) return false;
if (!isNaN(min) && v < min) return false;
if (!isNaN(max) && v > max) return false;
return true;
};
}
switch (typeof(value)) {
case "number":
return func(value, nan ? true : !isNaN(value));
case "string":
return str && value ? jBD.isNumber(Number(value), {nan: nan, int: int}) : false;
default:
return false;
}
};
/**
* 是否为String
*
* @param {*} value 判断值
* @param {boolean} [empty=false] 空值是否为字符串
* @returns {boolean}
*/
jBD.isString = (value, empty) => {
return (typeof(value) == "string") && (empty === true ? true : value.length > 0);
};
/**
* 是否为函数
*
* @param {*} value 判断值
* @returns {boolean}
*/
jBD.isFunction = value => typeof(value) == "function";
/**
* 是否为数组
*
* @param {*} value 判断值
* @param {boolean} [arg=false] arguments是否为数组
* @returns {boolean}
*/
jBD.isArray = (value, arg) => {
switch (jBD.type(value, true)) {
case "array":
return true;
case "arguments":
return arg === true ? arg : false;
default:
return false;
}
};
/**
* 是否为对象
*
* @param {*} value 判断值
* @param {string|boolean} [arg=object] 只识别Object
* @returns {boolean}
*/
jBD.isObject = (value, arg) => {
let result = typeof(value) == "object";
switch (arg) {
case false:
return result && (value !== null);
default:
return result && (value ? (value.constructor == Object) : false);
case true:
case "any":
return result;
}
};
/**
* 是否为Promise
*
* @param {*} value 判断值
* @returns {boolean}
*/
jBD.isPromise = value => jBD.type(value, true) == "promise";
/**
* 是否为Generator
*
* @param {*} value 判断值
* @param {boolean} [obj=false] 是否检测对象
* @returns {boolean}
*/
jBD.isGenerator = (value, obj) => {
const isFunc = jBD.isFunction,
isObj = obj => isFunc(obj.next) && isFunc(obj.throw);
if (!value) return false;
if (!isFunc(value)) return obj === true ? isObj(value) : false;
let main = value.constructor;
if (main.name == "GeneratorFunction" || main.displayName == "GeneratorFunction") return true;
return isObj(main.prototype);
};
/**
* 是否为JSON
*
* @param {*} value 判断值
* @param {object} [out=null] out为状态机参数
* @param {function} [callback]
* @returns {boolean}
*/
jBD.isJSON = (value, out, callback) => {
if (typeof(value) != "string" || value.length < 2) return false;
let data = (o, v) => {
o.type = v[0];
o.escape = v[1];
o.index = v[2];
return o;
},
result = (o, v) => {
if (callback) callback(o, v);
return false;
},
type, escape;
if (callback === void(0)) callback = out;
if (!out || typeof (out) != "object") out = {};
else {
type = out.type;
escape = out.escape;
}
if (!jBD.isFunction(callback)) callback = null;
if (!(type instanceof Array)) type = [];
escape = escape === true;
let index = 0,
len = type.length - 1,
str = len >= 0 && type[len] == 1;
if (!/^['"\[\{]/.test(value)) return result(data(out, [type, escape, -1]));
for (let char of value) {
if (escape) escape = false;
else {
switch (char = char.codePointAt()) {
case 92:
if (!str) return result(data({}, [type, escape, index]), out);
escape = true;
break;
case 34:
case 39:
if (!str) {
str = true;
len = type.push(char) - 1;
}
else if (char == type[len]) {
type.pop();
len--;
str = false;
}
break;
case 91:
case 123:
if (!str) {
len = type.push(char + 2) - 1;
}
break;
case 93:
case 125:
if (!str) {
if (char != type[len]) return result(data({}, [type, escape, index]), out);
type.pop();
len--;
}
break;
}
}
index++;
if (len == -1) break;
}
result(null, data(out, [type, escape, index]));
return len == -1;
};
/**
* 是否为jQuery对象
*
* @param {*} value 判断值
* @returns {boolean}
*/
jBD.isjQuery = value => jBD.isObject(value) && value.jquery;
/**
* 是否为DOM对象
*
* @param {*} value 判断值
* @returns {boolean|number}
*/
jBD.isDOM = value => jBD.type(value, true) == "dom" && value.nodeType;
/**
* 是否为日期
*
* @param {*} value 判断值
* @param {boolean} [str=false] 是否检验字符串
* @returns {boolean}
*/
jBD.isDate = (value, str) => {
switch (jBD.type(value, true)) {
default:
return false;
case "date":
return true;
case "string":
if (!(str === true)) return false;
value = value.trim().split(" ");
if (!value[0] || value.length > 2) return false;
value[0] = value[0].replace(/-/g, "/").split("/");
if (value[0].length != 3) return false;
let year = Number(value[0][0]),
month = Number(value[0][1]),
day = Number(value[0][2]);
if (isNaN(year) || year < 1900) return false;
if (isNaN(month) || month < 1 || month > 12) return false;
if (isNaN(day) || day < 1 || day > 31) return false;
switch (month) {
case 2:
if (day > (28 + ((!(year % 4) && (year % 100)) || !(year % 400) ? 1 : 0))) return false;
break;
case 4:
case 6:
case 9:
if (day > 30) return false;
break;
}
return value.length > 1 ? jBD.isTime(value[1], true) : true;
}
};
/**
* 是否为时间
*
* @param {*} value 判断值
* @param {boolean} [str=false] 是否检验字符串
* @returns {boolean}
*/
jBD.isTime = (value, str) => {
switch (jBD.type(value, true)) {
default:
return false;
case "date":
return true;
case "string":
if (!(str === true)) return false;
value = value.trim().replace(/\./g, ":").split(":");
if (value.length < 3 || value.length > 4) return false;
if (value.length == 3) value.push("0");
let hour = Number(value[0]),
minute = Number(value[1]),
second = Number(value[2]),
msecond = Number(value[3]);
if (isNaN(hour) || isNaN(minute) || isNaN(second) || isNaN(msecond)) return false;
if (hour < 0 || hour > 23) return false;
if (minute < 0 || minute > 59) return false;
if (second < 0 || second > 59) return false;
if (msecond < 0 || msecond > 999) return false;
return true;
}
};
/**
* 是否为guid
*
* @param {*} value 判断值
* @returns {boolean}
*/
jBD.isGuid = value => {
if (typeof(value) != "string") return false;
value = value.replace(/([{}])/g, "");
if (value.length != 36) return false;
value = value.toLowerCase().split("-");
if (value.length != 5) return false;
for (let i = 0, dic = [8, 4, 4, 4, 12], c, d; i < value.length; i++) {
d = value[i];
if (d.length != dic[i]) return false;
for (c of d) {
c = c.codePointAt();
if (!((c >= 48 && c <= 57) || (c >= 97 && c <= 102))) return false;
}
}
return true;
};
/**
* 是否是两者之间,不安全判定方式
*
* @param {number} value
* @param {number} b1
* @param {number} b2
* @returns {boolean}
*/
jBD.between = (value, b1, b2) => {
value = Number(value);
b1 = Number(b1);
b2 = Number(b2);
return value >= b1 && value <= b2;
};
/**
* 获得回调函数
*
* @param {Array|arguments} value
* @param {number} [index=0] 参数序号
* @returns {function/null}
*/
jBD.callback = (value, index) => {
if (!jBD.isArray(value, true)) return null;
if (!jBD.isNumber(index)) index = 0;
if (index < 0 || index >= value.length) return null;
value = value[value.length - 1];
return jBD.isFunction(value) ? value : null;
};
/**
* 对象遍历
*
* @param {Array|object|string|set|map} value
* @param {function} callback
* @param {boolean|number|object} opt 参数
* @param {boolean} [opt.detail=false] 详细内容
* @param {boolean} [opt.force=false] 强制array识别
* @param {boolean} [opt.index=0] 起始遍历位置,value=array时生效
* @param {boolean} [opt.desc=false] 倒序排列,value=array时生效
* @returns {boolean}
*/
jBD.each = (value, callback, opt) => {
if (!value || !jBD.isFunction(callback)) return false;
let detail, force, index, desc, list;
switch (typeof(opt)) {
case "object":
if (opt) {
detail = opt.detail;
force = opt.force;
index = opt.index;
desc = opt.desc
}
break;
case "boolean":
detail = opt;
break;
case "number":
index = opt;
break;
}
detail = detail === true;
force = force === true;
index = jBD.isNumber(index) ? index : 0;
desc = desc === true;
list = value;
switch (force ? "array" : jBD.type(value, true)) {
default:
return false;
case "string":
case "set":
list = Array.from(value);
case "array":
case "arguments":
if (index < 0) return false;
let n = desc ? -1 : 1,
i = (desc ? list.length - 1 : 0) + index * n,
l, d;
if (i < 0 || i >= list.length) l = i * -1;
else l = desc ? 1 : list.length * -1;
for (; i + l; i += n) {
d = list[i];
if (callback.apply(value, [d, i, detail ? jBD.type(d, true) : value, value]) === false) return false;
}
return true;
case "object":
case "function":
desc = list;
list = new Map();
for (index in desc) list.set(index, desc[index]);
case "map":
let o = [null, null],
k, v;
for (o of list) {
k = o[0];
v = o[1];
if (callback.apply(value, [v, k, detail ? jBD.type(v, true) : value, value]) === false) return false;
}
return true;
}
};
/**
* 去重复
*
* @param {Array} value
* @param {boolean} [write=false] 是否更改源
* @returns {Array}
*/
jBD.unique = (value, write) => {
if (!jBD.isArray(value, true)) return [];
let result = Array.from(new Set(value));
if (write === true) {
value.splice(0, value.length);
for (let i = 0; i < result.length; i++) value.push(result[i]);
}
return result;
};
/**
* 判断值是否存在
*
* @param {*} value
* @param {Array|object|set|map} list
* @param {function} callback
* @returns {boolean}
*/
jBD.has = (value, list, callback) => {
let result = false;
if (!jBD.isFunction(callback)) callback = null;
switch (jBD.type(list, true)) {
case "array":
case "arguments":
case "object":
jBD.each(list, (d, k) => {
if (!Object.is(value, d)) return;
result = true;
if (callback && (callback(k) === true)) return;
return false;
});
break;
case "set":
case "map":
result = list.has(value);
break;
}
return result;
};
/**
* 深入合并,前项覆盖后项
*
* @param {*} src
* @param {*} dest
* @param {boolean|object} opt 参数,opt=boolean时,默认匹配opt.deep参数
* @param {boolean} [opt.deep=false] 深入copy
* @param {boolean} [opt.write=true] 改写dest
* @param {function} callback
* @returns {*}
*/
jBD.clone = (src, dest, opt, callback) => {
let type = jBD.type(src, true),
simple = jBD.isSimple(dest);
if (!jBD.has(type, ["array", "object", "function", "set", "map"])) return src;
else if (!simple && jBD.type(dest, true) != type) return dest;
const cbset = (dest, key, odata, ndata, type) => {
return callback ? callback.apply(dest, [key, ndata, type, odata]) : ndata;
},
upset = (type, dest, k, d, t) => {
switch (type) {
case "set":
return dest.add(d);
case "map":
return dest.set(k, cbset(dest, k, dest.has(k) ? dest.get(k) : void(0), d, t));
case "array":
return dest.length > k ? dest[k] = cbset(dest, k, dest[k], d, t) : dest.push(cbset(dest, k, void(0), d, t));
default:
return dest[k] = cbset(dest, k, dest[k], d, t);
}
},
deepset = (state, src, dest, k) => {
if (!state) return;
jBD.clone(src, dest, true, (key, nd, t, od) => callback ? callback.apply(dest, [k + "." + key, nd, t, od]) : nd);
};
if (opt === void(0)) opt = dest;
if (callback === void(0)) callback = opt;
let deep, write;
switch (typeof(opt)) {
case "object":
if (opt) {
deep = opt.deep;
write = opt.write;
}
break;
case "boolean":
deep = opt;
break;
}
deep = deep === true;
write = write !== false;
if (!jBD.isFunction(callback)) callback = null;
if (simple) {
switch (type) {
case "function":
return src;
case "set":
dest = new Set();
break;
case "map":
dest = new Map();
break;
case "array":
dest = [];
break;
default:
dest = {};
break;
}
}
if (!write) dest = jBD.clone(dest, null, true);
jBD.each(src, (d, k, t) => {
if (Object.is(src, d)) return;
if (!deep) upset(type, dest, k, d, t);
else {
switch (t) {
default:
upset(type, dest, k, d, t);
break;
case "null":
case "undefined":
upset(type, dest, k, null, "null");
break;
case "object":
upset(type, dest, k, {}, "object");
deepset(jBD.isObject(dest[k]), d, dest[k], k);
break;
case "array":
case "arguments":
upset(type, dest, k, [], "array");
deepset(d.length > 0 && jBD.isArray(dest[k]), d, dest[k], k);
break;
case "set":
upset(type, dest, k, new Set(), "set");
deepset(d.size > 0 && jBD.type(dest[k], true) == "set", d, dest[k], k);
break;
case "map":
upset(type, dest, k, new Map(), "map");
deepset(d.size > 0 && jBD.type(dest[k], true) == "map", d, dest[k], k);
break;
}
}
}, true);
return dest;
};
})(this);
/**
* ==========================================
* Name: jBD‘s Class
* Author: Buddy-Deus
* CreTime: 2016-04-06
* Description: BD‘s Class
* Log:
* 2016-04-06 重写代码
* 2016-04-20 重构List,以函数形式存在,合并Queue和Stack以配对函数区分
* 2016-04-21 重构ChinaDate,以函数形式存在,内部引用TChinaDate类
* 2016-11-24 基于ES6改写
* ==========================================
*/
(own => {
const initClassError = function () {
if (this.getError || this.setError || this.lastError) return;
this.__error__ = [];
this.errorMax = 5;
this.getError = function (index) {
index = parseInt(jBD.isNumber(index) && index >= 0 ? index : -1);
let list = this.__error__;
return list.length < 1 ? null : list[index < 0 ? list.length - 1 : index];
};
this.setError = function (level, code, msg) {
if (arguments.length < 2) code = level;
if (arguments.length < 3) msg = code;
if (!jBD.has(level, ["log", "info", "error"])) level = "log";
if (!jBD.isNumber(code)) code = -1;
if (!jBD.isString(msg)) msg = "";
let list = this.__error__,
err = {level, code, msg};
while (list.length >= this.errorMax) list.shift();
list.push(err);
this.call("error", [err]);
return list[list.length - 1];
};
this.lastError = function () {
let list = this.__error__;
return list.length > 0 ? list[list.length - 1] : null;
};
},
initClassEvent = function () {
if (this.on || this.off || this.call) return;
this.__event__ = {};
this.on = function (key, func) {
let each = (o, l, n) => {
for (let i = n, f; i < l.length; i++) {
f = l[i];
switch (jBD.type(f, true)) {
case "function":
o.push(f);
break;
case "array":
each(o, f, 0);
break;
}
}
},
list = this.__event__[key] || (this.__event__[key] = []);
each(list, arguments, 1);
return this;
};
this.off = function (key, func) {
if (arguments.length == 0) this.__event__ = {};
else if (typeof(func) != "function") this.__event__[key] = [];
else {
let list = this.__event__[key];
if (list && list.length > 0) {
for (let i = 0; i < list.length; i++) {
if (func !== list[i]) i++;
else list.splice(i, 1);
}
}
}
return this;
};
this.call = function (key, arg) {
let list = this.__event__[key];
if (list && list.length > 0) {
if (arguments.length < 2) arg = [];
else if (!jBD.isArray(arg)) arg = [arg];
for (let i = 0; i < list.length; i++) list[i].apply(this, arg);
}
return this;
};
};
/*
====================================
= 类名: TSeal
= 功 能: 密封类生成
= 对象属性:
= className = 函数名
= 对象函数:
= clone = 复制本体
= Create = 初始化
====================================
*/
own.TSeal = (() => {
function TSeal () {}
TSeal.extend = function (childAPI) {
if (!jBD.isObject(childAPI)) throw new Error(console.error("[TSeal] object is null"));
const className = childAPI.className || "TSeal",
parentClass = TSeal,
initChild = function () {
initClassError.call(this);
initClassEvent.call(this);
this["create"].apply(this, arguments);
return this;
};
let childClass = null;
eval("childClass=function " + className + "(){return initChild.apply(this,arguments);}");
childClass.prototype = Object.create(parentClass.prototype);
childClass.className = className;
(CLASS => {
jBD.each(childAPI, (d, k) => {
if (Object.is(CLASS[k], d)) return;
CLASS[k] = jBD.clone(d, true);
});
})(childClass.prototype);
return childClass;
};
TSeal.className = "TSeal";
TSeal.prototype = {
className: "TSeal",
create: function () { return this; },
free: function () {},
clone: function () { return jBD.clone(this, true); }
};
return TSeal;
})();
/*
====================================
= 类名: TObject
= 功 能: 基类
= 类函数:
= extend = 继承函数
= 对象属性:
= className = 函数名
= 对象函数:
= clone = 复制本体
= create = 初始化
= free = 注销
= super = 继承
====================================
*/
own.TObject = (() => {
function TObject () {}
TObject.extend = function (childAPI, parentClass) {
const getClassName = target => {
if (target) {
if (typeof(target) == "function" && /^function ([a-zA-Z][a-zA-Z0-9_-]*)/.test(target.toString())) return RegExp.$1;
if (target.className) return target.className;
}
return "TObject";
},
initChild = function (parentClass, childAPI, arg) {
if (typeof(childAPI) == "function") {
childAPI = childAPI();
for (let k in childAPI) if (!Object.is(this[k], childAPI[k])) this[k] = childAPI[k];
}
if (!childAPI.hasOwnProperty("create")) parentClass.apply(this, arg);
else {
initClassError.call(this);
initClassEvent.call(this);
childAPI["create"].apply(this, arg);
}
return this;
};
parentClass = parentClass || this;
childAPI = childAPI || {};
let className = [getClassName(parentClass), getClassName(childAPI)],
childClass = null;
if (className[0] == className[1] && className[1] == "TObject") className[1] = "Child";
eval("childClass=function " + className[1] + "(){return initChild.call(this,parentClass,childAPI,arguments);}");
childClass.__super__ = parentClass;
childClass.prototype = Object.create(parentClass.prototype);
childClass.prototype.__super__ = parentClass.prototype;
childClass.prototype.className = className[1];
childClass.className = className[1];
jBD.each(parentClass, (d, k) => {
if (k == "className" || Object.is(childClass[k], d)) return;
if (k == "__super__") childClass["__super__"][k] = d;
else childClass[k] = d;
});
(CLASS => {
jBD.each(childAPI, (d, k, t) => {
if (k == "__super__" || Object.is(CLASS[k], d)) return;
CLASS[k] = jBD.clone(d, true);
});
})(typeof (childAPI) == "function" ? childClass : childClass.prototype, true);
return childClass;
};
TObject.className = "TObject";
TObject.prototype = {
className: "TObject",
create: function () { return this; },
free: function () {},
super: function (method, arg, cls) {
if (typeof(method) != "string") return;
if (!cls) cls = this.__super__;
else {
if (typeof(cls) == "string" && cls) {
let _this = this.__super__;
do {
if (_this.className != cls) _this = _this.__super__;
else {
cls = _this;
break;
}
}
while (_this.__super__);
}
if (!cls.className) return;
}
method = cls[method];
if (!method) return;
else if (!jBD.isFunction(method)) return method;
else if (jBD.isNull(arg, true)) return method.call(this);
else return method.apply(this, jBD.isArray(arg, true) ? arg : [arg]);
},
clone: function () { return jBD.clone(this, true); }
};
return TObject;
})();
own.TCache = (TObject => {
return TObject.extend({
className: "TCache",
create: function (size) {
this.max = size > 0 ? size : 128;
this.index = 0;
this.length = 0;
this.cache = Buffer.alloc(this.max);
},
free: function () {
this.cache = null;
},
surplus: function () {
return this.max - this.offset();
},
offset: function () {
return this.index + this.length;
},
resize: function (force) {
if (force === true) this.clear();
else {
if (this.length > 0) this.cache.copy(this.cache, 0, this.index, this.offset());
this.index = 0;
}
return this.surplus();
},
clear: function () {
this.index = 0;
this.length = 0;
return this;
},
push: function (buf) {
let offset = buf.byteOffset,
count = buf.byteLength,
write;
while (count > 0) {
write = Math.min(count, (write = this.surplus()) > 0 ? write : this.resize());
if (write < 1) write = this.resize(true);
buf.copy(this.cache, this.offset(), offset, offset + write);
this.length += write;
offset += write;
count -= write;
if (this.parse) this.parse();
}
return this;
},
remove: function (size) {
size = Math.min(size, this.length);
this.index += size;
this.length -= size;
return this;
}
});
})(own.TObject);
/*
====================================
= 类名: TList
= 功 能: 队列类
= 对象属性:
= length = 数据长度
= type = 数据限定类型
= first = 首个数据
= last = 尾端数据
= 对象函数:
= clear = 清空数据
= sort = 数据排序,接受自定义排序函数
= each = 数据检索,遍历函数为true时,删除遍历项
= set = 设置数据,校验数据类型
= del = 删除数据
= add = 添加数据,校验数据类型
= addList = 批量添加数据
= push = 先进后出,添加数据
= pop = 先进后出,获取数据
= put = 先进先出,添加数据
= poll = 先进先出,获取数据
====================================
*/
own.TList = (TObject => {
const isType = (obj, type) => {
let objType;
if (!type || type == "*" || (type == (objType = jBD.type(obj, true)))) return true;
if (type == "object" && (objType == "null" || objType == "undefined")) return false;
if (objType != "object") return false;
if (type == "date" && obj.className == "TChinaDate") return true;
return false;
},
fmtIndex = (index, def, max) => {
index = jBD.isNumber(index) ? index : def;
if (index < 0) index = -1;
else if (index >= max) index = max;
return index;
},
setData = (own, data) => {
let i;
for (i = 0; i < own.length; i++) delete own[i];
for (i = 0; i < data.length; i++) own[i] = data[i];
if ((own.length = data.length) > 0) {
own.first = own[0];
own.last = own[own.length - 1];
}
else {
own.first = null;
own.last = null;
}
};
return TObject.extend({
className: "TList",
create: function (type) {
this.data = [];
this.type = jBD.isString(type) ? type : "*";
this.length = 0;
this.onChange = null;
},
free: function () { this.clear(); },
valueOf: function () { return this.data; },
clear: function () {
this.data = [];
this.length = 0;
setData(this, this.data);
if (this.onChange) this.onChange("clear");
return this;
},
sort: function (func) {
if (func = jBD.isFunction(func) ? func : null) this.data.sort(func);
else this.data.sort();
setData(this, this.data);
if (this.onChange) this.onChange("sort");
return this;
},
each: function (func) {
if (jBD.isFunction(func)) {
for (let i = 0, r; i < this.length;) {
if ((r = func(this.data[i])) === true) this.del(i);
else if (r === false) break;
else i++;
}
}
return this;
},
"set": function (index, data) {
index = fmtIndex(index, -1, this.length);
if (!isType(data, this.type)) return -1;
this.data[index] = data;
if (this.onChange) this.onChange("set", {index: index, data: data});
return index;
},
del: function (index) {
let result;
if (this.length == 0) return null;
index = fmtIndex(index, 0, this.length - 1);
if (index <= 0) result = this.data.shift();
else if (index >= this.length - 1) result = this.data.pop();
else {
result = this.data[index];
this.data.splice(index, 1);
}
setData(this, this.data);
if (this.onChange) this.onChange("del", {index: index});
return result;
},
add: function (data, index) {
index = fmtIndex(index, this.length, this.length);
if (!isType(data, this.type)) return -1;
if (index <= 0) {
this.data.unshift(data);
index = 0;
}
else if (index >= this.length) this.data.push(data);
else this.data.splice(index, 0, data);
setData(this, this.data);
if (this.onChange) this.onChange("add", {index: index, data: data});
return index;
},
addList: function (data, index) {
if (jBD.isArray(data) && data.length > 0) {
index = fmtIndex(index, this.length, this.length);
jBD.each(data, function (d, i) {
this.add(d, index + i);
});
}
return this;
},
push: function (data) { return this.add(data, this.length); },
pop: function () { return this.del(this.length); },
put: function (data) { return this.add(data, 0); },
poll: function () { return this.del(0); }
});
})(own.TSeal);
/*
====================================
= 类名: TChinaDate
= 功 能: 中文日期类
= 对象函数:
= getTime = 获取当前毫秒数
= setTime = 设置当前时间
= toString = 转换为字符串
====================================
*/
own.TChinaDate = (TObject => {
const ct = {
monthInfoDt: new Date(1900, 0, 31),
monthInfo: [
0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,
0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0
],
termInfo: [
0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693,
263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758
],
tianGan: ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"],
diZhi: ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"],
monthStr: ["月", "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"],
dayStr: [
["日", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"],
["初", "十", "廿", "卅", " "]
],
termStr: [
"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至",
"小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
],
zodiacStr: ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"]
},
getTGDZ = num => {
num = jBD.isNumber(num) ? num : 0;
return ct.tianGan[num % 10] + ct.diZhi[num % 12];
},
getZodiac = num => ct.zodiacStr[(num - 4) % 12],
getTermDate = (year, month) => {
return (new Date((31556925974.7 * (year - 1900) + ct.termInfo[month % ct.termInfo.length] * 60000) + Date.UTC(1900, 0, 6, 2, 5))).getUTCDate();
},
getTerm = (year, month, date) => {
let term = [getTermDate(year, month * 2), getTermDate(year, month * 2 + 1)];
for (let i = 0; i < term.length; i++) {
if (term[i] == date) return ct.termStr[(month * 2 + i) % ct.termStr.length];
}
return "";
},
getYear = num => getTGDZ(num - 1864),
getMonth = (num, leap) => {
return (leap ? "闰" : "") + ct.monthStr[num % ct.monthStr.length];
},
getDay = num => {
return ct.dayStr[1][(num - num % 10) / 10] + ct.dayStr[0][num % 10 + (num % 10 ? 0 : 10)];
};
let TChinaDate = TObject.extend({
className: "TChinaDate",
create: function (dt) {
this.nt = {year: 0, month: 0, day: 0};
this.dt = new Date();
this.Year = "";
this.Month = "";
this.Day = "";
this.Term = "";
this.Zodiac = "";
this.cMonth = "";
this.cDay = "";
this.IsLeap = false;
this.setTime(dt);
},
valueOf: function () { return this.getTime(); },
getTime: function () { return this.dt.getTime(); },
/**
* 设置时间
*
* @public
* @param {date} dt
* @returns {object} this
*/
setTime: function (dt) {
const getLeapYearMonth = year => {
return ct.monthInfo[year - ct.monthInfoDt.getFullYear()] & 0xf;
},
getLeapYearDay = year => {
return getLeapYearMonth(year) ? ((ct.monthInfo[year - ct.monthInfoDt.getFullYear()] & 0x10000) ? 30 : 29) : 0;
},
getTotalYearDay = year => {
let sum = 348,
minfo = ct.monthInfo[year - ct.monthInfoDt.getFullYear()];
for (let i = 0x8000; i > 0x8; i >>= 1) sum += (minfo & i) ? 1 : 0;
return sum + getLeapYearDay(year);
},
getTotalMonthDay = (year, month) => {
return (ct.monthInfo[year - ct.monthInfoDt.getFullYear()] & (0x10000 >> month)) ? 30 : 29;
};
if (jBD.isDate(dt)) this.dt.setTime(dt.getTime());
let temp = 0,
leap = 0,
offset = parseInt((this.dt - ct.monthInfoDt) / 86400000),
i;
this.nt.year = 0;
this.nt.month = 14;
this.nt.day = offset + 40;
for (i = ct.monthInfoDt.getFullYear(); i < ct.monthInfoDt.getFullYear() + ct.monthInfo.length && offset > 0; i++) {
temp = getTotalYearDay(i);
offset -= temp;
this.nt.month += 12;
}
if (offset < 0) {
offset += temp;
i--;
this.nt.month -= 12;
}
this.nt.year = i;
this.IsLeap = false;
leap = getLeapYearMonth(i);
for (i = 1; i < 13 && offset > 0; i++) {
if (leap > 0 && i == (leap + 1) && !this.IsLeap) {
i--;
this.IsLeap = true;
temp = getLeapYearDay(this.nt.year);
}
else
temp = getTotalMonthDay(this.nt.year, i);
if (this.IsLeap && i == (leap + 1)) this.IsLeap = false;
offset -= temp;
if (!this.IsLeap) this.nt.month++;
}
if (offset < 0) {
offset += temp;
i--;
this.nt.month--;
}
else if (offset == 0 && leap > 0 && i == leap + 1) {
if (!this.IsLeap) {
i--;
this.nt.month--;
}
this.IsLeap = !this.IsLeap;
}
this.cYear = getTGDZ(this.nt.year - 1864);
this.cMonth = getTGDZ(this.nt.month);
this.cDay = getTGDZ(this.nt.day);
this.nt.month = i;
this.nt.day = offset + 1;
this.Year = getYear(this.nt.year);
this.Month = getMonth(this.nt.month, this.IsLeap);
this.Day = getDay(this.nt.day);
this.Term = getTerm(this.nt.year, this.nt.month, this.dt.getDate());
this.Zodiac = getZodiac(this.dt.getFullYear());
return this;
},
/**
* 转换成字符串
*
* @public
* @param {string} [fmt=Y年(Z) M月 D T]
* @returns {string}
*/
toString: function (fmt) {
let result = jBD.isString(fmt) ? fmt : "Y年(Z) M月 D T";
if (/((CY|CM|Y|M|D|T|Z)+)/.test(result)) {
fmt = {
"CY+": this.cYear,
"CM+": this.cMonth,
"CD+": this.cDay,
"Y+": this.Year,
"M+": this.Month,
"D+": this.Day,
"T+": this.Term,
"Z+": this.Zodiac
};
jBD.each(fmt, function (d, k) {
let rxp = new RegExp("(" + k + ")", "g");
if (rxp.test(result)) result = result.replace(rxp, d + "");
});
}
return result.trim();
}
});
TChinaDate.toString = function (fmt, date) {
if (date == void(0) && jBD.isDate(fmt)) {
date = fmt;
fmt = "";
}
return (new TChinaDate(date)).toString(fmt);
};
return TChinaDate;
})(own.TSeal);
/*
====================================
= 类名: TChinaDate
= 功 能: 中文日期类
= 对象函数:
= New = 获取新Guid
= toString = 获取字符串
= toByteArray = 获取字节数据
====================================
*/
own.TGuid = (TObject => {
const rnd = l => Math.round(Math.random() * (Math.pow(2, 8 * l) - 1)),
com = (s, l) => {
while (s.length < l * 2) s = "0" + s;
return s;
},
des = (r, d) => {
d.reverse();
for (let i = 0; i < d.length; i++) if (d[i].length > 0) r.push(parseInt("0x" + d[i]));
},
gd = [4, 2, 2, 2, 6];
let TGuid = TObject.extend({
className: "TGuid",
create: function (data) {
const fmt = (d, i, t, list) => {
switch (t) {
case "string":
d = "0x" + d;
break;
case "number":
if (!isNaN(d = parseInt(d))) break;
default:
return false;
}
if (d < 0 || d >= Math.pow(2, 8 * gd[i])) return false;
list[i] = d;
};
this.value = [0, 0, 0, 0, 0];
switch (jBD.type(data, true)) {
case "string":
data = data.replace(/^(\{)|(\})$/g, "").split("-");
break;
case "array":
if (data.length == gd.length) break;
default:
data = [];
break;
}
if (data.length == gd.length) {
if (jBD.each(data, fmt)) this.value = data;
}
},
valueOf: function () { return this.toString(); },
toString: function () {
let value = this.value,
result = "";
for (let i = 0; i < value.length; i++)
result += com(value[i].toString(16), gd[i]) + (i < value.length - 1 ? "-" : "");
return result;
},
toByteArray: function () {
let value = this.value,
result = [];
for (let i = 0; i < value.length; i++)
des(result, value[i].toString(16).split(/(\w{2})/g));
return result;
},
New: function () {
this.value = [rnd(4), rnd(2), rnd(2), rnd(2), rnd(6)];
return this;
}
});
TGuid.toString = function () { return (new TGuid()).New().toString(); };
TGuid.toByteArray = function () { return (new TGuid()).New().toByteArray(); };
TGuid.New = function () { return (new TGuid()).New(); };
return TGuid;
})(own.TSeal);
/**
* 队列函数
*
* @param {string} [type=*] 限定类型,对输入内容进行过滤
* @returns {object}
*/
own.List = type => (new own.TList(type));
/**
* 中文日期函数
*
* @param {date} [dt=now]
* @returns {object}
*/
own.ChinaDate = dt => (new own.TChinaDate(dt));
own.NewGuid = () => (new own.TGuid()).New();
own.EmptyGuid = () => (new own.TGuid());
})(this);
/**
* ==========================================
* Name: jBD‘s Asyn for ES6
* Author: Buddy-Deus
* CreTime: 2016-04-06
* Description: BD‘s Callback/Deferred for ES6
* Log:
* 2016-04-06 重写代码
* 2017-02-10 去除函数默认参数,增加适配
* 2017-02-22 增加ES6 Promise支持
* ==========================================
*/
(own => {
let TCallback, TDeferred, TPromise;
/*
====================================
= 类名: TCallback
= 功 能: 回调类
= 对象函数:
= lock = 锁定状态
= unlock = 去除锁定
= add = 添加函数
= del = 删除指定函数
= fire = 触发调用
= fireWith = 触发调用,改变this指向
= empty = 清空回调列表
= unique = 去除重复函数
= has = 检测是否存在指定函数
====================================
*/
TCallback = (TObject => {
const getFuncs = (list, callback) => {
jBD.each(list, (d, k, t) => {
switch (t) {
case "function":
callback(d);
break;
case "array":
if (d.length > 0) getFuncs(d, callback);
break;
}
}, true);
},
eachFuncs = (list, callback) => {
let i = 0;
while (i < list.length) {
if (callback(i, list[i]) !== false) i++;
}
},
fireFuncs = (list, data, once, done, prog) => {
if (list.length < 1) return done;
eachFuncs(list, (i, f) => {
f.apply(data[0], data[1]);
if (once) list.splice(i, 1);
if (prog) prog();
if (once) return false;
});
if (done) done();
return null
};
return TObject.extend({
className: "TCallback",
create: function (opt, limit, callback) {
this.locked = false;
this.length = 0;
this.__func = [];
this.__arg = null;
this.__opt = opt;
this.__limit = limit;
this.__callback = callback || null;
},
free: function () {
this.__opt = null;
this.__callback = null;
this.__func = null;
this.__arg = null;
},
lock: function () { return this.locked = true; },
unlock: function () { return this.locked = false; },
on: function () {
if (!this.locked) {
let opt = this.__opt,
func = this.__func,
arg = this.__arg;
getFuncs(arguments, d => {
func.push(d);
if (func.length > this.limit) func.pop();
});
this.length = func.length;
if (opt.unique) this.unique();
if (opt.memory && opt.fire && arg) fireFuncs(func, arg, opt.once, this.__callback, d => this.length = func.length);
}
return this;
},
off: function () {
if (!this.locked) {
let func = this.__func;
if (arguments.length == 0) func = this.__func = [];
else {
getFuncs(arguments, d => {
eachFuncs(func, (i, f) => {
if (Object.is(d, f)) {
func.splice(i, 1);
return false;
}
})
});
}
this.length = func.length;
}
return this;
},
fire: function () { return this.fireWith(this, arguments); },
fireWith: function (own, args, done) {
if (arguments.length < 2) args = [];
if (arguments.length < 1) own = this;
let opt = this.__opt,
arg;
this.__arg = arg = [own, args.slice ? args.slice() : args];
if (opt.memory && !opt.fire) {
opt.fire = true;
if (opt.limit) this.__arg = null;
}
else {
let func = this.__func;
fireFuncs(func, arg, opt.once, done, d => this.length = func.length);
if (this.__callback) this.__callback.apply(arg[0], arg[1]);
}
return this;
},
unique: function () {
if (!this.locked) this.length = (this.__func = Array.from(new Set(this.__func))).length;
return this;
},
has: function (func) { return this.__func.indexOf(func) != -1; }
});
})(jBD.TSeal);
/*
====================================
= 类名: TDeferred
= 功 能: 异步类(观察者模式)
= 对象函数:
= empty = 清空回调列表
= promise = 去除重复函数
= resolve = 触发成功
= reject = 触发失败
= alarm = 触发警告
= notify = 触发进度
= on = 绑定事件
= off = 解除绑定
= 对象事件:
= done = 成功
= fail = 失败
= warn = 警告
= progress = 进度
= always = 结束
====================================
*/
TDeferred = (TObject => {
let STATE = {
inited: 0,
pending: 1,
resolved: "resolve",
rejected: "reject"
},
Deferred;
Deferred = TObject.extend({
className: "TDeferred",
/**
* 初始化函数
*
* @param {number} [limit=50] 回调上限
* @param {function} [callback] 最终回调,在触发always最后调用
*/
create: function (limit, callback) {
let _this = this,
event = _this.__event = {
done: jBD.Callback(limit).fire(),
fail: jBD.Callback(limit).fire(),
warn: jBD.Callback(limit).fire(),
progress: jBD.Callback(limit).fire(),
always: jBD.Callback(limit, callback).fire()
},
action = _this.__action = {
resolve: event.done,
reject: event.fail,
alarm: event.warn,
notify: event.progress
},
promise = _this.__promise = {
state: STATE.inited,
on: function () {
_this.on.apply(_this, arguments);
return this;
},
off: function () {
_this.off.apply(_this, arguments);
return this;
},
promise: function () { return _this.promise.apply(_this, arguments); }
};
_this.state = STATE.inited;
_this.__owner = void(0);
_this.__surp = 0;
event.done.on(e => {
_this.__promise.state = _this.state = STATE.resolved;
event.fail.lock();
event.warn.lock();
event.progress.lock();
});
event.fail.on(e => {
_this.__promise.state = _this.state = STATE.rejected;
event.done.lock();
event.warn.lock();
event.progress.lock();
});
jBD.each(event, (d, k) => {
promise[k] = _this[k] = function () {
d.on(Array.from(arguments));
return this;
};
});
jBD.each(action, (d, k) => {
_this[k] = function () {
_this[k + "With"](_this, arguments);
return this;
};
_this[k + "With"] = function (own, arg) {
own = own || _this.__owner;
d.fireWith(own, arg);
if (_this.state == k) event.always.fireWith(own, arg);
else if (k == "notify" && --_this.__surp < 1) _this.resolveWith(own, arg);
return this;
};
});
},
/**
* 释放函数
*/
free: function () {
this.__promise = null;
this.__event = null;
this.__action = null;
},
/**
* 绑定事件
*
* @param {string} tag
* @param {function|Array} callback
* @returns {Window.TDeferred}
*/
on: function (tag, callback) {
if (this.__event[tag]) this.__event[tag].on(callback);
return this;
},
/**
* 解除绑定
*
* @param {string} [tag]
* @returns {Window.TDeferred}
*/
off: function (tag) {
if (arguments.length == 0) jBD.each(this.__event, d => d.off());
else if (this.__event[tag]) this.__event[tag].off();
return this;
},
/**
* 返回操作者模式
*
* @param {object} [own] 所有者
* @param {number} [max] 最大done次数,用于适配剩余模式
* @returns {null|*}
*/
promise: function (own, max) {
if (this.state == STATE.inited || this.state == STATE.pending) {
this.__promise.state = this.state = STATE.pending;
if (arguments.length == 1 && jBD.isNumber(own)) max = own;