export const getPrototypeOf = function (obj) { return Object.getPrototypeOf ? Object.getPrototypeOf(obj) : obj.__proto__; }; export const isObject = function isObject(something) { const type = typeof something; return something !== null && (type === 'function' || type === 'object'); }; export const iterateInheritedPrototype = function iterateInheritedPrototype(callback, fromCtor, toCtor, includeToCtor = true) { let proto = fromCtor.prototype || fromCtor; const toProto = toCtor.prototype || toCtor; while (proto) { if (!includeToCtor && proto === toProto) break; if (callback(proto) === false) break; if (proto === toProto) break; proto = getPrototypeOf(proto); } }; export const toObject = function toObject(something, options = {}) { const obj = {}; if (!isObject(something)) return obj; const excludes = options.excludes || ['constructor']; const { enumerable = true, configurable = 0, writable = 0 } = options; const defaultDesc = {}; if (enumerable !== 0) defaultDesc.enumerable = enumerable; if (configurable !== 0) defaultDesc.configurable = configurable; if (writable !== 0) defaultDesc.writable = writable; iterateInheritedPrototype((proto) => { Object.getOwnPropertyNames(proto).forEach((key) => { if (excludes.indexOf(key) >= 0) return; if (Object.prototype.hasOwnProperty.call(obj, key)) return; const desc = Object.getOwnPropertyDescriptor(proto, key); const fnKeys = ['get', 'set', 'value']; fnKeys.forEach((k) => { if (typeof desc[k] === 'function') { const oldFn = desc[k]; desc[k] = function (...args) { return oldFn.apply(Object.prototype.hasOwnProperty.call(options, 'bindTo') ? options.bindTo : this, args); }; } }); Object.defineProperty(obj, key, Object.assign(Object.assign({}, desc), defaultDesc)); }); }, something, options.till || Object, false); return obj; }; export const isPlainObject = function isPlainObject(something) { return Object.prototype.toString.call(something) === '[object Object]'; };