美文网首页IT@程序员猿媛简友广场
如何写一个完整的JavaScript类,将现有代码整合

如何写一个完整的JavaScript类,将现有代码整合

作者: 程就人生 | 来源:发表于2019-12-09 21:01 被阅读0次

    最近在使用HTML5的WebSocket,在写WebSocket测试用例的时候,很多方法都分散在页面的JavaScript里面,很想把这些零碎的方法整合成一个类,然后以js文件的形式引入,引入后以类的形式调用,这样页面看起来岂不是干净了很多。

    说做就做,拿起以前做的demo,就在这上面进行修改吧。SpringBoot整合Netty与websocket客户端进行对话 通过这篇笔记,把里面的js整理一下,整理以后对比一下修改前后的结果。

    在把HTML5页面里的WebSocket代码整理成一个类的同时,也遇到了一些问题:
    1.在JavaScript里面,如何声明一个类;
    2.类里面的公有属性和私有属性如何区分;
    3.类里面的一个方法即需要在外面调用,有需要在内部调用,这该如何写;
    一直都在零零碎碎地写一些JS方法,要整合成一个功能相对完整的类来,还是需要翻下资料的。

    下面就直接上代码,websocket.js的内容如下:

    /**
     * websocket的构造方法
     * @param wconfig 连接websocket的基础参数
     */
    var WebSocketHtml5 = function(wconfig){
        //ws客户端,私有变量
        var socket;
        //参数传递
        var wconfig = wconfig;
        //把本身引用赋值到一变量上
        var _self = this;
        //避免重复连接
        var lockReconnect = false;
        //重连标识
        var reconnectFlag;
        //重连时间,4S
        var reconnectTime = 4000;
        //心跳检测时间50s
        var heartTime = 50000;
        //websocket默认是传输字符串的,需要改为arraybuffer二进制传输类型
        var binaryType = wconfig.binaryType!=undefined&&wconfig.binaryType!=''?wconfig.binaryType:"";
        //连接参数
        var wsUrl = "ws://localhost:"+wconfig.imServerPort+"/websocket/"+wconfig.userUid;
        //接收到的二位数组,第一个是消息类型,第二个是消息体
        var resData;
        //创建连接,公有方法
        this.createWebSocket=function(){
            try {
                if(typeof(WebSocket) == "undefined") {  
                    console.log("您的浏览器不支持WebSocket");  
                }else{
                    console.log("您的浏览器支持WebSocket");  
                }
                socket = new WebSocket(wsUrl);
                //websocket默认是传输字符串的,需要改为arraybuffer二进制传输类型         
                //socket.binaryType = binaryType;
                //初始化
                init();
            } catch(e) {
                console.log('catch');
                reconnect();
            }
        }   
        //初始化
        function init() {
            socket.onclose = function () {
                console.log('链接关闭');
                reconnect();
            };
            socket.onerror = function() {
                console.log('发生异常了');
                reconnect();
            };
            socket.onopen = function () {
                //心跳检测重置
                heartCheck.start(socket, wconfig);
            };
            socket.onmessage = function (event) {
                //接收数据
                var resData = JSON.parse(event.data);
                //心跳保持
                heartCheck.start(socket, wconfig);
                //接收数据的返回
                receive(resData);
            }
        }
        /**
         * 消息的发送
         * msgData 消息结构体,包括以下几个属性
         * @param toUser 消息接收人
         * @param textContent 消息内容
         * @param contentType 消息类型
         */
        this.send = function (msgData){     
            //发送数据
            socket.send(JSON.stringify(msgData));
        }   
        //重新连接
        function reconnect() {
          if(lockReconnect) {
            return;
          };
          lockReconnect = true;
          //没连接上会一直重连,设置延迟避免请求过多
          reconnectFlag && clearTimeout(reconnectFlag);
          reconnectFlag = setTimeout(function () {
              _self.createWebSocket();
            lockReconnect = false;
          }, reconnectTime);//重连时间
        }   
        //生成消息的uuid
        function uuid() {
            var s = [];
            var hexDigits = "0123456789abcdef";
            for (var i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
            s[8] = s[13] = s[18] = s[23] = "";
         
            var uuid = s.join("");
            return uuid;
        }
    }
    //心跳检测
    var heartCheck =  {
        timeout: 50000,//心跳检测时间
        timeoutObj: null,
        serverTimeoutObj: null,
        start: function(socket, wconfig){
            var self = this;
            this.timeoutObj && clearTimeout(this.timeoutObj);
            this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
            this.timeoutObj = setTimeout(function(){
                //这里发送一个心跳,后端收到后,返回一个心跳消息,
                //onmessage拿到返回的心跳就说明连接正常
                console.log(' socket心跳检测');
                //发送心跳 start
                var object={}
                object.content = "心跳检测";
                object.toUser = wconfig.userUid;
                object.fromUser= wconfig.userUid;
                socket.send(JSON.stringify(object));
                //发送心跳 end
                self.serverTimeoutObj = setTimeout(function() {
                    socket.close();
                }, self.timeout);
            }, this.timeout)
        }
    };
    

    下面再看页面里的使用:

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" >
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    </head>
    <body>
    <p>发送信息:<input type="text" id="txt" ></input></p>
    <p>接收人:<input type="text" id="toUser" ></input></p>
    <p><button id="button" >发送消息</button></p>
    <p id="recvContent">
    
    </p>
    <script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
    <script th:src="@{/websocket.js}"></script>
    <script th:inline="javascript" >
        //websocket连接相关参数
        var imData={};
        imData.userUid=[[${userUid}]];
        imData.imServerPort=[[${imServerPort}]];
        //以类的形式进行调用
        var websocketHtml5 = new WebSocketHtml5(imData);
        //创建websocket
        websocketHtml5.createWebSocket();
        //获取接收到的数据
        var receive = function(resData){
            if(resData!=undefined) {
                $("#recvContent").append('<div style="width:300px;text-align:left;"><span >'+resData.fromUser + '发送:' + resData.content + '</span></div><br/>');
            } 
        };
        //发送信息回车键
        $("#txt").keydown(function(event){ 
            if(event.keyCode==13){ 
                $("#button").click();
            } 
        });    
        //按钮点击事件
        $("#button").click(function(){
            var object={}
            object.content = $("#txt").val();
            object.toUser = $("#toUser").val();
            object.fromUser= imData.userUid;
            $("#txt").val("");
            $("#recvContent").append('<div style="width:300px;text-align:right;"><span >发送给'+object.toUser + ':' + object.content + '</span></div><br/>');
            websocketHtml5.send(object);
        });    
    </script>
    
    </body>
    </html>
    

    最后,验证结果,和修改之前的测试结果保持一致,这说明已经成功地将方法整合成了一个类;


    在JavaScript里面编写类,大致有三种方法,一种是构造函数方式,一种是原型方式,还有一种就是构造函数+原型,这里使用的是构造函数+原型的混合方式。下面就这三种类型一一说明一下。

    一、构造函数式
    顾名思义,像写函数一样写类;

    function test(a,b){
       // 用var定义,代表类的私有属性
        var a=a;
      // 用this关键字定义,代表类的公有属性,可通过实例访问
        this.b=b;
     //这个很重要,对于公有方法,可以使用该变量进行访问
       var _self=this;
      // 私有方法,只能在类的内部访问
      funciton c(){
         console.log("这是类内部的私有方法");
      }
      //公有方法,可以通过类的实例进行访问
      this.d=function(){
         console.log("这是类内部的公有方法");
      }
    }
    

    二、原型方式
    原型方式其实就是上面示例中的心跳检测,这种写法看起来比较优雅、舒服;

    var test={
    a:'',//public属性
    b:'',//公有属性
    //公有方法
    c:function(a,b){
    this.a=a;
    this.b=b;
    console.log("这是类内部的公有方法");
    }
    }
    

    参考资料:
    https://www.cnblogs.com/xdp-gacl/p/3700840.html

    相关文章

      网友评论

        本文标题:如何写一个完整的JavaScript类,将现有代码整合

        本文链接:https://www.haomeiwen.com/subject/qqubgctx.html