UNPKG

fonteditor-core

Version:

fonts (ttf, woff, woff2, eot, svg, otf) parse, write, transform, glyph adjust.

239 lines (201 loc) 5.97 kB
/** * @file 语言相关函数 * @author mengke01(kekee000@gmail.com) */ export function isArray(obj) { return obj != null && toString.call(obj).slice(8, -1) === 'Array'; } export function isObject(obj) { return obj != null && toString.call(obj).slice(8, -1) === 'Object'; } export function isString(obj) { return obj != null && toString.call(obj).slice(8, -1) === 'String'; } export function isFunction(obj) { return obj != null && toString.call(obj).slice(8, -1) === 'Function'; } export function isDate(obj) { return obj != null && toString.call(obj).slice(8, -1) === 'Date'; } export function isEmptyObject(object) { for (const name in object) { // eslint-disable-next-line no-prototype-builtins if (object.hasOwnProperty(name)) { return false; } } return true; } /** * 为函数提前绑定前置参数(柯里化) * * @see http://en.wikipedia.org/wiki/Currying * @param {Function} fn 要绑定的函数 * @param {...Array} cargs cargs * @return {Function} */ export function curry(fn, ...cargs) { return function (...rargs) { const args = cargs.concat(rargs); // eslint-disable-next-line no-invalid-this return fn.apply(this, args); }; } /** * 方法静态化, 反绑定、延迟绑定 * * @param {Function} method 待静态化的方法 * @return {Function} 静态化包装后方法 */ export function generic(method) { return function (...fargs) { return Function.call.apply(method, fargs); }; } /** * 设置覆盖相关的属性值 * * @param {Object} thisObj 覆盖对象 * @param {Object} thatObj 值对象 * @param {Array.<string>} fields 字段 * @return {Object} thisObj */ export function overwrite(thisObj, thatObj, fields) { if (!thatObj) { return thisObj; } // 这里`fields`未指定则仅overwrite自身可枚举的字段,指定`fields`则不做限制 fields = fields || Object.keys(thatObj); fields.forEach(field => { // 拷贝对象 if ( thisObj[field] && typeof thisObj[field] === 'object' && thatObj[field] && typeof thatObj[field] === 'object' ) { overwrite(thisObj[field], thatObj[field]); } else { thisObj[field] = thatObj[field]; } }); return thisObj; } /** * 深复制对象,仅复制数据 * * @param {Object} source 源数据 * @return {Object} 复制的数据 */ export function clone(source) { if (!source || typeof source !== 'object') { return source; } let cloned = source; if (isArray(source)) { cloned = source.slice().map(clone); } else if (isObject(source) && 'isPrototypeOf' in source) { cloned = {}; for (const key of Object.keys(source)) { cloned[key] = clone(source[key]); } } return cloned; } // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. // @see underscore.js export function throttle(func, wait) { let context; let args; let timeout; let result; let previous = 0; const later = function () { previous = new Date(); timeout = null; result = func.apply(context, args); }; return function (...args) { const now = new Date(); const remaining = wait - (now - previous); // eslint-disable-next-line no-invalid-this context = this; if (remaining <= 0) { clearTimeout(timeout); timeout = null; previous = now; result = func.apply(context, args); } else if (!timeout) { timeout = setTimeout(later, remaining); } return result; }; } // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. // @see underscore.js export function debounce(func, wait, immediate) { let timeout; let result; return function (...args) { // eslint-disable-next-line no-invalid-this const context = this; const later = function () { timeout = null; if (!immediate) { result = func.apply(context, args); } }; const callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); } return result; }; } /** * 判断两个对象的字段是否相等 * * @param {Object} thisObj 要比较的对象 * @param {Object} thatObj 参考对象 * @param {Array} fields 指定字段 * @return {boolean} 是否相等 */ export function equals(thisObj, thatObj, fields) { if (thisObj === thatObj) { return true; } if (thisObj == null && thatObj == null) { return true; } if (thisObj == null && thatObj != null || thisObj != null && thatObj == null) { return false; } // 这里`fields`未指定则仅overwrite自身可枚举的字段,指定`fields`则不做限制 fields = fields || (typeof thisObj === 'object' ? Object.keys(thisObj) : []); if (!fields.length) { return thisObj === thatObj; } let equal = true; for (let i = 0, l = fields.length, field; equal && i < l; i++) { field = fields[i]; if ( thisObj[field] && typeof thisObj[field] === 'object' && thatObj[field] && typeof thatObj[field] === 'object' ) { equal = equal && equals(thisObj[field], thatObj[field]); } else { equal = equal && (thisObj[field] === thatObj[field]); } } return equal; }