在js中仿java的枚举类型设计实例

简介

在javascript中,像EventTarget.addEventListener()Document.createElement() 等方法,只接收指定字符串作为参数。比如:

const okButton = document.getElementById("button_ok");
okButton.addEventListener('click', () => console.log('button_ok clicked!'), false);

在上述代码中,我们必须按Events 中所定义的类型字符串(如:click, load)传参,否则程序就不能正常工作。本文将介绍如何通过objectclass两种封装形式,分别实现枚举类型。

object封装

  • index.html
<!DOCTYPE>
<html>
<head>
    <meta charset="UTF-8">
    <title>enum</title>
</head>
<body>
<button id="button_cancel">Cancel</button>
<button id="button_ok">OK</button>
<script src="object_script.js"></script>
</body>
</html>
  • object_script.js
(function () {
    'use strict';

    /** 事件 */
    const Event = {
        CLICK: "click",
        LOAD: "load"
    };
    deepFreeze(Event);

    /** 响应 */
    const Response = {
        OK: {
            code: 100,
            message: "ok"
        },
        ERROR: {
            code: 900,
            message: "error"
        }
    };
    deepFreeze(Response);

    addEventListener(window, Event.LOAD, () => {
        const okButton = document.getElementById("button_ok");
        addEventListener(okButton, Event.CLICK, () => alert(generateResponseText(Response.OK)));
        const cancelButton = document.getElementById("button_cancel");
        addEventListener(cancelButton, Event.CLICK, () => alert(generateResponseText(Response.ERROR)));
    });

    /**
     * object深度冻结
     * @param {Object} object 对象
     */
    function deepFreeze(object) {
        Object.freeze(object);
        for (const key in object) {
            const value = object[key];
            if (!object.hasOwnProperty(key) || typeof value != "object" || Object.isFrozen(value)) {
                continue;
            }
            deepFreeze(value);
        }
    }

    /**
     * 事件监听器登记
     * @param {EventTarget} target 目标
     * @param {String} event 事件
     * @param {Function} listener 监听器
     * @throws {Error} 错误
     */
    function addEventListener(target, event, listener) {
        if (event === undefined) {
            throw new Error("event is undefined");
        }
        target.addEventListener(event, listener, false);
    }

    /**
     * 响应字符串生成
     * @param {Object} response 响应
     * @return {String} 响应字符串
     * @throws {Error} 错误
     */
    function generateResponseText(response) {
        if (response === undefined) {
            throw new Error("response is undefined");
        }
        return "[" + response.code + "] " + response.message;
    }
})();

class封装

  • index_class.html
<!DOCTYPE>
<html>
<head>
    <meta charset="UTF-8">
    <title>enum</title>
</head>
<body>
<button id="button_cancel">Cancel</button>
<button id="button_ok">OK</button>
<script src="class_script.js"></script>
</body>
</html>
  • class_script.js
(function () {
    'use strict';

    /** 值存储类 */
    class HasValue {
        /**
         * @param {Object} value 值
         */
        constructor(value) {
            this.value = value;
        }
    }

    /** 事件类 */
    class Event extends HasValue {
    }
    /** 事件常量 */
    const Events = {
        CLICK: new Event("click"),
        LOAD: new Event("load")
    };
    deepFreeze(Events);

    /** 响应类 */
    class Response {
        /**
         * @param {Number} code 编码
         * @param {String} message 消息
         */
        constructor(code, message) {
            this.code = code;
            this.message = message;
        }
    }
    /** 响应常量 */
    const Responses = {
        OK: new Response(100, "ok"),
        ERROR: new Response(900, "error")
    };
    deepFreeze(Responses);

    addEventListener(window, Events.LOAD, () => {
        const okButton = document.getElementById("button_ok");
        addEventListener(okButton, Events.CLICK, () => alert(generateResponseText(Responses.OK)));
        const cancelButton = document.getElementById("button_cancel");
        addEventListener(cancelButton, Events.CLICK, () => alert(generateResponseText(Responses.ERROR)));
    });

    /**
     * object深度冻结
     * @param {Object} object 对象
     */
    function deepFreeze(object) {
        Object.freeze(object);
        for (const key in object) {
            const value = object[key];
            if (!object.hasOwnProperty(key) || typeof value != "object" || Object.isFrozen(value)) {
                continue;
            }
            deepFreeze(value);
        }
    }

    /**
     * 事件监听器登记
     * @param {EventTarget} target 目标
     * @param {Event} event 事件实例
     * @param {Function} listener 监听器
     * @throws {Error} 错误
     */
    function addEventListener(target, event, listener) {
        if (!(event instanceof Event)) {
            throw new Error("event is not instance of Event");
        }
        target.addEventListener(event.value, listener, false);
    }

    /**
     * 响应字符串生成
     * @param {Object} response 响应
     * @return {String} 响应字符串
     * @throws {Error} 错误
     */
    function generateResponseText(response) {
        if (!(response instanceof Response)) {
            throw new Error("response is not instance of Response");
        }
        return "[" + response.code + "] " + response.message;
    }
})();

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注