UNPKG

@schukai/monster

Version:

Monster is a simple library for creating fast, robust and lightweight websites.

136 lines (121 loc) 3.6 kB
/** * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html * * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact Volker Schukai. * * SPDX-License-Identifier: AGPL-3.0 */ import { instanceSymbol } from "../constants.mjs"; export { Base }; /** * This is the base class from which the most classes are derived. * * This class has besides a `toString` which returns the json representation of the object * also a functionality to check if an object is an instance of a class. * * Therefore, the class has a static method <code>[Symbol.hasInstance](that)</code> which returns true if the object * is an instance of the class. * * <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance">MDN Symbol.hasInstance</a> * * Derived classes should implement a static getter `instanceSymbol` which returns a unique symbol. * * <code lang="javascript"> * static get [instanceSymbol]() { * return Symbol.for("@schukai/monster/types/base"); * } * </code> * * The class was formerly called Object. * * @since 1.5.0 * @copyright Volker Schukai * @summary The base class for the most classes in the monster library */ class Base extends Object { /** * @return {string} */ toString() { return JSON.stringify(this); } /** * This method is called by the `instanceof` operator. * @return {symbol} * @since 2.1.0 */ static get [instanceSymbol]() { return Symbol.for("@schukai/monster/types/base"); } /** * This method is called by the `instanceof` operator. * @param that * @return {boolean} * @since 2.1.0 */ static [Symbol.hasInstance](that) { if ( that === undefined || that === null || (typeof that !== "object" && typeof that !== "function") ) { return false; } const thatClass = Object.getPrototypeOf(that); if ( thatClass === undefined || thatClass === null || (typeof thatClass !== "object" && typeof thatClass !== "function") ) { return false; } if (checkInstanceSymbol.apply(this, [thatClass]) === true) { return true; } // this call the static method of the super class, if there is one return super[Symbol.hasInstance](that); } } /** * this function checks if the class has a static getter <code>instanceSymbol</code>, * and if the value of this getter is equal to the * * @private * @param obj * @return {boolean|any|boolean} * @since 2.1.0 */ function checkInstanceSymbol(obj) { if (this.hasOwnProperty(instanceSymbol) === false) { return false; } const proto = obj?.constructor; if ( proto === undefined || proto === null || (typeof proto !== "object" && typeof proto !== "function") ) { return false; } if (proto.hasOwnProperty(instanceSymbol) !== true) { return checkInstanceSymbol.apply(this, [obj.__proto__]); } const symbol = proto[instanceSymbol]; if (symbol === undefined) { if (obj.__proto__) { return checkInstanceSymbol(obj.__proto__); } else { return false; } } if (symbol === this[instanceSymbol]) { return true; } return checkInstanceSymbol.apply(this, [obj.__proto__]); }