/** * @description fallback function * @throws ReferenceError * @returns {never} */ functioninvalidArgumentsHandler() { thrownewReferenceError("There's no function that matches the length and types of arguments you provided."); } invalidArgumentsHandler.__count = 0;
/** * @param {*}obj * @returns {String}the type of `obj`, in lower case */ functiongetType(obj) { if(obj === null) return"null"; if(obj === undefined) return"undefined"; if(obj.constructor && obj.constructor.name) return obj.constructor.name.toLowerCase(); returnObject.prototype.toString.call(obj).slice(8, -1).toLowerCase(); }
/** * @description define `attr` method of `obj` as a flex-length function. * @param {Object}obj The object to operate on. * @param {String}attr The method name of `obj` for `func` * @param {Function}func * @returns {Object}the modified obj */ functiondefineFlexMethod(obj, attr, func, argtype) { if(getType(argtype) === "undefined") { argtype = newArray(func.length); for(let i = 0; i < func.length; i++) { argtype[i] = "any"; } } if(typeof func !== "function") { thrownewTypeError("The third argument should be a function!"); } if(getType(argtype) !== "array") { thrownewTypeError("The fourth argument should be an array, if specified!"); } if(argtype.length !== func.length) { thrownewRangeError("Array's length should be equal to the provided function's args count!"); } let prevMethod = obj[attr]; if(!["function", "undefined"].includes(getType(prevMethod))) { thrownewTypeError(`Non-function-type attribute ${attr} already exists!`); } if(prevMethod === undefined) { // Set the default fallback function prevMethod = invalidArgumentsHandler; } else { if(!("__count"in prevMethod)) { prevMethod.__count = 0; } else { if(getType(prevMethod.__count) !== "number") { thrownewTypeError(`attribute ${attr} already has __count attribute, and it is not a number!`); } } } obj[attr] = function () { /* This function is generated by defineFlexMethod() */ if(arguments.length === func.length) { for(let i = 0; i < arguments.length; i++) { if(argtype[i] !== "any" && getType(arguments[i]) !== argtype[i]) { return prevMethod.apply(obj, arguments); } } return func.apply(obj, arguments); } else { return prevMethod.apply(obj, arguments); } }; obj[attr].__count = prevMethod.__count + 1; return obj; }
/** * @description fallback function * @throws ReferenceError * @returns {never} */ functioninvalidArgumentsHandler() { thrownewReferenceError("There's no function that matches the length and types of arguments you provided."); } invalidArgumentsHandler.__count = 0;