zoukankan      html  css  js  c++  java
  • 第十五节 JS面向对象实例及高级

    实例:面向对象的选项卡

      把面向过程的程序,改写成面向对象的形式

        原则:不能有函数套函数,但可以有全局变量

        过程:

          onload —— 改写成 构造函数,其中window.onload的功能是在页面加载时“初始换整个程序”,类似于构造函数——初始化整个对象

          全局变量 —— 改写成 属性  

          函数 —— 改写成 方法

        改错:this、时间、闭包、传参

      对象与闭包:通过闭包传递this

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <title>面向对象选项卡</title>
      6     <style>
      7         #div1 button{background: white;}
      8         #div1 button.active{background: yellow;}
      9         #div1 div{
     10             width: 200px;
     11             height: 200px;
     12             background: #cccccc;
     13             display: none;
     14         }
     15     </style>
     16     <script>
     17         // window.onload = function () {
     18         //     var oDiv = document.getElementById('div1');
     19         //     var aBtn = oDiv.getElementsByTagName('button');
     20         //     var aDiv = oDiv.getElementsByTagName('div');
     21         //
     22         //     for (var i = 0; i < aBtn.length; i++) {
     23         //         aBtn[i].index = i;
     24         //
     25         //         aBtn[i].onclick = function () {
     26         //             for (var i = 0; i < aBtn.length; i++) {
     27         //                 aBtn[i].className = '';
     28         //                 aDiv[i].style.display = 'none';
     29         //             };
     30         //             this.className = 'active';
     31         //             aDiv[this.index].style.display = 'block';
     32         //         }
     33         //     }
     34         // };
     35 
     36         // //此时我们要把上述语句改写为面向对象的代码
     37         // var aBtn = null;    //定义全局变量
     38         // var aDiv = null;    //定义全局变量
     39         //
     40         // window.onload = function () {
     41         //     var oDiv = document.getElementById('div1');
     42         //     aBtn = oDiv.getElementsByTagName('button');
     43         //     aDiv = oDiv.getElementsByTagName('div');
     44         //
     45         //     for (var i = 0; i < aBtn.length; i++) {
     46         //         aBtn[i].index = i;
     47         //         aBtn[i].onclick = fnClick;    //函数没有嵌套,只是调用
     48         //     }
     49         // };
     50         //
     51         // function fnClick() {
     52         //     for (var i = 0; i < aBtn.length; i++) {
     53         //         aBtn[i].className = '';
     54         //         aDiv[i].style.display = 'none';
     55         //     }
     56         //     this.className = 'active';   //此处this表示当前被点击的那个按钮
     57         //     aDiv[this.index].style.display = 'block';
     58         // }
     59 
     60         //在进行一次改写
     61         window.onload = function () {
     62             new TabSwitch('div1');
     63         };
     64 
     65         function TabSwitch(id) {
     66             var _this = this;
     67 
     68             var oDiv = document.getElementById(id);
     69 
     70             this.aBtn = oDiv.getElementsByTagName('button');
     71             this.aDiv = oDiv.getElementsByTagName('div');
     72 
     73             for (var i = 0; i < this.aBtn.length; i++) {
     74                 this.aBtn[i].index = i;
     75                 // this.aBtn[i].onclick = this.fnClick;    //此时fnClick已经不是一个函数了,而是一个方法
     76                 this.aBtn[i].onclick = function () {
     77                     _this.fnClick(this);
     78                 };
     79 
     80             }
     81         }
     82 
     83         TabSwitch.prototype.fnClick = function (oBtn) {
     84             // alert(this);    //[object HTMLButtonElement]
     85 
     86             for (var i = 0; i < this.aBtn.length; i++) {
     87                 this.aBtn[i].className = '';
     88                 this.aDiv[i].style.display = 'none';
     89             }
     90             oBtn.className = 'active';    //此时this代表当前的对象
     91             this.aDiv[oBtn.index].style.display = 'block';
     92         };
     93     </script>
     94 </head>
     95 <body>
     96     <div id="div1">
     97         <button class="active">aaa</button>
     98         <button>bbb</button>
     99         <button>ccc</button>
    100         <div style="display: block">111</div>
    101         <div>222</div>
    102         <div>333</div>
    103     </div>
    104 </body>
    105 </html>
    View Code

     Json方式的面向对象

      把方法包在一个Json里

    <script>
        // var json = {
        //     a:12,
        //     b:5,
        //     c:'abc',
        //     d:function () {alert('a');}
        // };
        // alert(json.a);  //12
        // json.d();   //a
    
        // var json = {
        //     a:12,
        //     show:function () {alert(this);}    //此时this即指json
        // };
        // json.show();    //[object Object]
    
        //改写67.html,较67.html更加简单,但是缺点是不适合多个对象,比如再创建一个其他用户时,又需要在创建一个Json对象
        var json = {
            name:'haha',
            qq:'123456789',
            showName:function (){
                alert('他的名字叫做:'+this.name);
            },
            showQQ:function () {
                alert('他的QQ号为:'+this.qq);
            }
        };
        json.showName();
        json.showQQ();
    </script>
    View Code

        有人称作——命名空间

    <script>
        var json = {};  //json中包含另外3个json
    
        json.common = {};
        json.fx = {};
        json.site = {};
    
        //在不同的json里面写同一个名字的函数,并且不会相互冲突
        json.common.getUser = function () {
            alert('a');
        };
        json.fx.getUser = function () {
            alert('b');
        };
        json.site.getUser = function () {
            alert('c');
        };
    
        json.common.getUser();
        json.fx.getUser();
        json.site.getUser();
    </script>
    View Code

        在公司里,把同一类方法,包在一起,既不会相互冲突,又方便查找

    引用 :用“=”处理,和复制相似,但是两者指向的是同一个事物,而不是两个

     1 <script>
     2     // var arr1 = [1,2,3];
     3     // var arr2 = arr1;
     4     //
     5     // arr2.push(4);
     6     //
     7     // alert(arr2);    //返回:1,2,3,4
     8     // alert(arr1);    //返回:1,2,3,4
     9     //原因是上面“arr2 = arr1;”语句知识把两个变量都指向了同一个数组,并不是指向两个不同的数组,此时该语句叫做“引用”,若想使其不相同,如下:
    10     var arr1 = [1,2,3];
    11     var arr2 = [];
    12 
    13     for (var i = 0; i<arr1.length; i++){
    14         arr2.push(arr1[i]);
    15     }
    16     arr2.push(4);
    17 
    18     alert(arr2);    //返回:1,2,3,4
    19     alert(arr1);    //返回:1,2,3
    20 </script>
    View Code

      对象的继承

        什么是继承:在原有的基础上,略作修改,得到一个新的类,并且不影响原有类的功能

     1 <script>
     2     function A() {      //A的属性都写在函数内,构造函数
     3         this.abc = 12;
     4     }
     5 
     6     A.prototype.show = function () {    //A的方法都现在原型上
     7         alert(this.abc);
     8     };
     9 
    10     function B() {
    11         A.call(this);   //此时this表示new B() 即新建的B对象  用call来继承父级的属性
    12     }
    13 
    14     // //继承属性
    15     // var obj = new B();
    16     // alert(obj.abc);    //返回12 当B方法内没有定义“A.call(this);”时,返回的是undefined
    17 
    18     // //继承父级的属性我们可以用call,但是继承父级的方法我们用什么呢?如下:
    19     // B.prototype = A.prototype;
    20     // var obj = new B();
    21     // obj.show();     //返回12
    22 
    23     //但是问题在于当B存在自己的方法的时候时,如:
    24     B.prototype = A.prototype;
    25 
    26     B.prototype.fn = function () {
    27         alert('abc');
    28     };
    29 
    30     var objB = new B();
    31     var objA = new B();
    32 
    33     objA.fn();  //返回 abc 按理说不应该弹出该结果,因为B继承A;但是这样一来A B就互相继承了
    34 </script>
    View Code

    拖拽和继承

      面向对象的拖拽——改写原有拖拽

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <title>面向对象的拖拽</title>
      6     <style>
      7         #div1{
      8             width: 200px;
      9             height: 200px;
     10             background: red;
     11             position: absolute;
     12         }
     13     </style>
     14     <script>
     15         // //面向过程的拖拽:
     16         // window.onload = function () {
     17         //     var oDiv = document.getElementById('div1');
     18         //
     19         //     oDiv.onmousedown = function (ev) {
     20         //         var oEvent = ev||event;
     21         //
     22         //         var disX = oEvent.clientX-oDiv.offsetLeft;
     23         //         var disY = oEvent.clientY-oDiv.offsetTop;
     24         //
     25         //         document.onmousemove = function (ev) {
     26         //             var oEvent = ev||event;
     27         //
     28         //             oDiv.style.left = oEvent.clientX-disX+'px';
     29         //             oDiv.style.top = oEvent.clientY-disY+'px';
     30         //         };
     31         //         document.onmouseup = function () {
     32         //             document.onmousemove = null;
     33         //             document.onmouseup = null;
     34         //         };
     35         //     };
     36         // };
     37 
     38         //面向对象的拖拽:
     39         //第一步:把所有的函数嵌套去掉
     40         //第二步:把所有在多个函数中用到的变量,改为全局变量
     41         // // var oDiv = null;
     42         // var disX = 0;
     43         // var disY = 0;
     44         //
     45         // function Drag(id) {
     46         //     oDiv = document.getElementById(id);
     47         //     oDiv.onmousedown = this.fnDown;
     48         // };
     49         //
     50         // function fnDown(ev) {
     51         //     var oEvent = ev||event;
     52         //
     53         //     disX = oEvent.clientX-oDiv.offsetLeft;
     54         //     disY = oEvent.clientY-oDiv.offsetTop;
     55         //
     56         //     document.onmousemove = fnMove;
     57         //     document.onmouseup = fnUp;
     58         // }
     59         // function fnMove(ev) {
     60         //     var oEvent = ev||event;
     61         //
     62         //     oDiv.style.left = oEvent.clientX-disX+'px';
     63         //     oDiv.style.top = oEvent.clientY-disY+'px';
     64         // }
     65         // function fnUp() {
     66         //     document.onmousemove = null;
     67         //     document.onmouseup = null;
     68         // }
     69 
     70         //第三步:把“var oDiv = null;”注释掉,把对象的属性用this表示,即把div当做属性,然后合理添加this
     71         // var oDiv = null;
     72         window.onload = function () {
     73             new Drag('div1');
     74         };
     75 
     76         function Drag(id) {
     77             var _this = this;
     78 
     79             this.disX = 0;
     80             this.disY = 0;
     81 
     82             this.oDiv = document.getElementById(id);
     83             this.oDiv.onmousedown = function (ev) {
     84                 _this.fnDown(ev);
     85             };
     86         };
     87 
     88         Drag.prototype.fnDown = function (ev) {
     89             var _this = this;
     90 
     91             var oEvent = ev||event;
     92 
     93             this.disX = oEvent.clientX-this.oDiv.offsetLeft;
     94             this.disY = oEvent.clientY-this.oDiv.offsetTop;
     95 
     96             document.onmousemove = function (ev) {
     97                 _this.fnMove(ev);
     98             };
     99             document.onmouseup = function (ev) {
    100                 _this.fnUp(ev);
    101             };
    102         };
    103         Drag.prototype.fnMove = function (ev) {
    104             var oEvent = ev||event;
    105 
    106             this.oDiv.style.left = oEvent.clientX-this.disX+'px';
    107             this.oDiv.style.top = oEvent.clientY-this.disY+'px';
    108         };
    109         Drag.prototype.fnUp = function () {
    110             document.onmousemove = null;
    111             document.onmouseup = null;
    112         };
    113 
    114         //此时我们就可以把这些拖拽操作的方法,提取出来放到一个js文件中,方便之后需要使用只需 src引入 来使用即可
    115     </script>
    116 </head>
    117 <body>
    118 <div id="div1"></div>
    119 </body>
    120 </html>
    View Code

      instanceof运算符:查看对象是否是某个类的实例

    使用继承

      限制范围的拖拽类

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>面向对象的拖拽</title>
     6     <style>
     7         #div1{
     8             width: 200px;
     9             height: 200px;
    10             background: red;
    11             position: absolute;
    12         }
    13         #div2{
    14             width: 200px;
    15             height: 200px;
    16             background: green;
    17             position: absolute;
    18         }
    19     </style>
    20     <script src="74Drag.js"></script>
    21     <script src="74limitDrag.js"></script>
    22     <script>
    23         window.onload = function () {
    24             new Drag('div1');
    25             new LimitDrag('div2');
    26         };
    27     </script>
    28 </head>
    29 <body>
    30 <div id="div1">普通拖拽</div>
    31 <div id="div2">范围受限制的拖拽</div>
    32 </body>
    33 </html>
    View Code
     1 function Drag(id) {
     2     var _this = this;
     3 
     4     this.disX = 0;
     5     this.disY = 0;
     6 
     7     this.oDiv = document.getElementById(id);
     8     this.oDiv.onmousedown = function (ev) {
     9         _this.fnDown(ev);
    10 
    11         return false;   //拖拽一个物体时,防止另一个物体中的文字被选中
    12     };
    13 };
    14 
    15 Drag.prototype.fnDown = function (ev) {
    16     var _this = this;
    17 
    18     var oEvent = ev||event;
    19 
    20     this.disX = oEvent.clientX-this.oDiv.offsetLeft;
    21     this.disY = oEvent.clientY-this.oDiv.offsetTop;
    22 
    23     document.onmousemove = function (ev) {
    24         _this.fnMove(ev);
    25     };
    26     document.onmouseup = function (ev) {
    27         _this.fnUp(ev);
    28     };
    29 };
    30 Drag.prototype.fnMove = function (ev) {
    31     var oEvent = ev||event;
    32 
    33     this.oDiv.style.left = oEvent.clientX-this.disX+'px';
    34     this.oDiv.style.top = oEvent.clientY-this.disY+'px';
    35 };
    36 Drag.prototype.fnUp = function () {
    37     document.onmousemove = null;
    38     document.onmouseup = null;
    39 };
    74Drag.js
     1 // 面向对象的继承
     2 function LimitDrag(id) {
     3     Drag.call(this, id);    //继承属性
     4 }
     5 
     6 for (var i in Drag.prototype) {
     7     LimitDrag.prototype[i] = Drag.prototype[i];
     8 }
     9 
    10 //覆盖掉其父级“Drag”的fnMove方法,并重写该方法
    11 LimitDrag.prototype.fnMove = function (ev) {
    12     var oEvent = ev||event;
    13 
    14     //重新写继承的父级方法
    15     var l = oEvent.clientX-this.disX;
    16     var t = oEvent.clientY-this.disY;
    17 
    18     if (l < 0) {    //重新父级方法,使拖拽左右不可拖出可视区
    19         l = 0;
    20     } else if (l>document.documentElement.clientWidth-this.oDiv.offsetWidth) {
    21         l = document.documentElement.clientWidth-this.oDiv.offsetWidth;
    22     }
    23 
    24     this.oDiv.style.left = l+'px';
    25     this.oDiv.style.top = t+'px';
    26 };
    74limitDrag.js

    继承的好处体现在,我把父级的方法继承过来,也可以根据自己需要重写所继承父级方法中不存在的东西

        构造函数伪装

          属性的继承

            原理:欺骗构造函数

          call的使用

    1 <script>
    2     function show(a, b) {
    3         alert('this是:'+this+'
    a是:'+a+'
    b是:'+b);
    4     }
    5 
    6     // show(12,5);     //返回:this是:[object Window]   a是:12   b是:5
    7     // show.call(12, 5);   //返回:this是:12   a是:5   b是:undefined  此时第一个参数即为this
    8     show.call('haha', 12, 5);   //this是:haha    a是:12    b是:5
    9 </script>
    View Code

    不使用“引用”的原型继承

     1 <script>
     2     function A() {      //A的属性都写在函数内,构造函数
     3         this.abc = 12;
     4     }
     5 
     6     A.prototype.show = function () {    //A的方法都现在原型上
     7         alert(this.abc);
     8     };
     9 
    10     function B() {
    11         A.call(this);   //此时this表示new B() 即新建的B对象  用call来继承父级的属性
    12     }
    13 
    14     // //继承属性
    15     // var obj = new B();
    16     // alert(obj.abc);    //返回12 当B方法内没有定义“A.call(this);”时,返回的是undefined
    17 
    18     // //继承父级的属性我们可以用call,但是继承父级的方法我们用什么呢?如下:
    19     // B.prototype = A.prototype;
    20     // var obj = new B();
    21     // obj.show();     //返回12
    22 
    23 
    24     // //但是问题在于当B存在自己的方法的时候时,如:
    25     // B.prototype = A.prototype;
    26     //
    27     // B.prototype.fn = function () {
    28     //     alert('abc');
    29     // };
    30     //
    31     // var objB = new B();
    32     // var objA = new B();
    33     //
    34     // objA.fn();  //返回 abc 按理说不应该弹出该结果,因为B继承A;但是这样一来A B就互相继承了,
    35 
    36     // 其实上述也是“引用”惹的祸,解决办法如下:复制,让他们指向不同的物体
    37     for (var i in A.prototype) {
    38         B.prototype[i] = A.prototype[i];
    39     }
    40     B.prototype.fn = function () {
    41         alert('abc');
    42     };
    43 
    44     var objB = new B();
    45     var objA = new B();
    46 
    47     objA.fn();
    48 </script>
    View Code

        原型链

          方法的继承

            原理:复制方法

          覆盖原型和方法复制

    系统对象

      本地对象(非静态对象)

        什么是本地对象:简单来说,需要进行实例化才能使用系统自带的类,叫做本地对象,常用非静态对象:Object、Function、Array、String、Boolean、Number、Date、RegExp(正则)、Error

      内置对象(静态对象)

        什么是本地对象:简单来说,凡是不需要new就能使用的对象就是内置对象,如Global(虚假对象,因为基本上用不到)、Math

    1 var obj = new Math();   //错误用法,因为它属于静态对象
    2 Math.ceil();    //正确使用方法 

      前两个对象不依赖于JS的执行环境,可以说是JS本身的对象

      宿主对象(JS的运行环境)

        由浏览器提供的对象,其实就是DOM、BOM;

        Node.js运行环境是后台,所以其宿主对象就是后台的一系列对象。

  • 相关阅读:
    2014 12 27 bestcoder 第一题
    大数阶乘问题!
    学校acm比赛题
    hdu1002 大数相加问题
    写于创建之初
    Linux指令 vi编辑,保存及退出
    Java基础-反射
    Java基础-接口与多态
    00023-layui表单有check、radio、switch,未选中时值不提交的解决
    00022-layui 显示表单,iframe父子页面传值
  • 原文地址:https://www.cnblogs.com/han-bky/p/10412299.html
Copyright © 2011-2022 走看看