JS面向对象

JS面向对象:

JS面向对象基础:
  1.什么是面向对象:即在不了解某个对象内部原理的情况下,我们就可以直接使用它的功能
      使用面向对象时,我们只关注对象提供的功能,不关注内部的细节
      面向对象是一种通用思想,并非只是在编程中才能使用


  2.面向对象编程(OOP)的特点:
      --抽象:抓住核心问题,把与问题相关的特征抽出来,放到系统里面
      --封装:不考虑内部实现,只考虑使用功能
      --继承:从父类对象上继承一些方法/属性,子类又有字节的一些新的属性(分为多重继承,多态)


  3.对象的组成:
    1)--属性:与变量是等价的,平常我们定义的变量的特点:自由的不属于任何一个对象,
          而当一个变量属于某个对象时,我们就叫这个变量为属性.
        var a=12;     //变量:自由的,不属于任何一个事物
        alert(a);
        var arr=[1,2,3,4];
        arr.a=12;     //属性:不自由,是属于一个对象的变量
        alert(arr.a);


     2)--方法:与函数是等价的,平常所写的函数的特点:是自由的,
        而当一个函数属于某个对象时我们就叫这个函数为方法
          function aaa(){     //函数:自由的
              alert('abc');
          }
          var arr=[1,2,3,4];
          arr.aaa=function(){   //方法:属于一个对象的函数
              alert('abc');
          }
          aaa();
          arr.aaa();


  4.面向对象中的this:指当前的方法属于哪个对象,this就指的是那个对象
          (之前我们为对象添加一个事件,即为对象添加一个方法)


  5.面向对象中的window:当我们定义一个全局的方法/函数时,它是属于window之下的一个方法
      function show(){    //全局的函数/方法,属于window
          alert(this);    //弹出[object window]
      }
      ==>等价于:
      window.show=function(){
          alert(this);    //弹出[object window]
      }


  6.注意的问题:我们不能在系统对象(如Array,Date等)中随意添加属性,方法,否则会覆盖已有方法和属性
          我们经常用object对象来添加属性/方法,因为其几乎没有自己的属性和方法,可防止与添加的产生冲突


  7.自定义第一个面向对象的小程序:
      var obj=new Object();
      obj.name='yufan';
      obj.myQQ='123456';
      obj.show=function(){
          alert('我的姓名:'+this.name);
          alert('我的QQ:'+this.myQQ);
      }
      obj.show();    //调用


  当有多个用户时,以上方法就会有大量重复的代码,所以我们需要封装成一个函数
      function addPerson(name,qq){
          //原料
          var obj=new Object();
          //加工
          obj.name=name;
          obj.myQQ=qq;
          obj.show=function(){
              alert('我的姓名:'+this.name);
              alert('我的QQ:'+this.myQQ);
          }
          //出厂
          return obj;
      }
      var obj1=addPerson('yufan','123456');    //创建对象
      var obj2=addPerson('red','456789');    //再次创建对象
      obj1.show();    //调用对象上面的方法
      obj2.show();
      alert(obj1.show==obj2.show);    //false


  注**上面的概念理解:
      --上面的addPerson函数叫做:构造函数(和普通的函数没有区别,只不过他的作用不同而已)
      --上面构造函数创建过程的方式叫做工厂方式(有原料,有加工,有出厂)
      --工厂方式有缺点:
          --没有new
               解决:当一个全局函数在调用时,前面加上new,则表示系统自己定义一个新对象
          --实例化对象时,每一个对象都有一个自己的方法,而这些对象的方法明明是一样的,却不能共用,会导致资源的浪费
              (上面obj1.show==obj2.show-->false)
              解决:用原型在所有创建的类上添加方法,使两个对象共用来自于原型上的方法
              (这时有obj1.show==obj2.show-->true)

          js面向对象最终的代码是:
          function addPerson(name,qq){
              //加new之后,系统自己会new一个对象出来,可不写:var this=new Object();
              this.name=name;
              this.myQQ=qq;
              //加new之后,系统自己会返回一个对象出来,可不写:return this;
          }
          addPerson.prototype.show=function(){    //用原型在所用创建的类上添加方法
              alert('我的姓名:'+this.name);
              alert('我的QQ:'+this.myQQ);
          }
          var obj1=new addPerson('yufan','123456');
          var obj2=new addPerson('red','456789');
          obj1.show();
          obj2.show();
          alert(obj1.show==obj2.show);    //true
  总结面向对象创建的方法:
       在构造函数上给对象添加属性,在原型上给对象添加方法
         我们经常采用这种面向对象全新的写法:混合的构造函数/原型方式

  8.js原型(prototype):类似CSS里面的class,用class时,可以一次给多个元素添加行外样式,
    使用原型时,可以一次给多个实例化对象添加方法,使资源得到共用
      var arr1=new Array(12,5,3);
      var arr2=new Array(12,5,3,4);
      arr1.sum=function(){ //arr1.sum方法相当于CSS里添加行间样式,一次只能给一个元素添加样式
          var result=0;
          for(var i=0;i<this.length;i++){
              result+=this[i];
          }
          return result;
      }
      arr1.sum();    //正确
      arr2.sum();    //会报错,因为没有为arr2添加sum方法
  ==>这时使用原型可以为多个对象添加方法,类似CSS里用class添加行外样式
      var arr1=new Array(12,5,3);
      var arr2=new Array(12,5,3,4);
      Array.prototype.sum=function(){  //prototype原型在类上添加方法
          var result=0;
          for(var i=0;i<this.length;i++){
              result+=this[i];
          }
          return result;
      }
      arr1.sum();    //正确
      arr2.sum();    //正确
  注**对象和类的区别
      var arr=new Array(1,2,3);
      --类:模子-->Array
      --对象:成品(产品)-->arr
      --prototype原型是往类里面加东西(Array.prototype.sum),而不是对象


js面向对象实例:
1.将一个面向过程的程序,改写成面向对象的形式
    --原则:不能有函数套函数,但可以有全局变量
2.过程:将平时写的面向过程的js选项卡,改写成面向对象的js选项卡
    --解决函数嵌套的问题(将嵌套的函数拿出来,放到外面,变成全局函数)
    --解决局部变量的问题,当局部变量在多个函数中使用时,将局部变量变成全局变量(否则会报错)
    --将window.onload(作用:初始化整个程序)变成 构造函数(作用:初始化整个对象)
    --将全局变量变成 -->对象的属性
    --将全局的函数变成 -->对象的方法

  

面向过程的js选项卡,改写成面向对象的js选项卡
CSS代码:
<style> .active{ background: red; } #div1 div{ 200px; height: 200px; background: #ccc; border:1px solid #000; display: none; margin-top: 20px; } </style> HTML代码: <div id="div1"> <input class="active" type="button" value="首页" /> <input type="button" value="新闻" /> <input type="button" value="咨询" /> <input type="button" value="教育" /> <div style="display: block;">1111</div> <div>2222</div> <div>3333</div> <div>4444</div> </div> JS代码: window.onload=function(){ var obj=new TabSwitch('div1'); }; function TabSwitch(id){ var _this=this; var oDiv=document.getElementById(id); this.aBtn=oDiv.getElementsByTagName('input'); this.aDiv=oDiv.getElementsByTagName('div'); for (var i = 0; i < this.aBtn.length; i++) { this.aBtn[i].index=i; this.aBtn[i].onclick=function(){ _this.btnClick(this); } } } TabSwitch.prototype.btnClick=function(oBtn){ for (var i = 0; i < this.aBtn.length; i++) { this.aBtn[i].className=''; this.aDiv[i].style.display='none'; } oBtn.className='active'; this.aDiv[oBtn.index].style.display='block'; }

3.改错:this,事件,闭包,传参

js面向对象高级:
1.json实现的面向对象:(又称单体)
    var json={
        name:'yufan',
        qq:'123456',
        showName:function(){
            alert('我的名字叫:'+this.name);
        },
        showQQ:function(){
            alert('我的QQ是:'+this.qq);
        }
    }
    json.showName();
    json.showQQ();
与OOP的方法相比json实现的创建对象优点是简单,但是该方法只适用创建单个对象,不适合多个对象
Json方式实现的对象的适用范围:
    --整个程序里只有一个对象,写起来比较简单


2.命名空间:可以让很多相同名字的函数同时存在
    --使用时,把方法包在一个json里面
      var zns={};
      zns.common={};
      zns.ms={};
      zns.color={};
      zns.common.getUser=function(){
          alert('a');
      }
     zns.ms.getUser=function(){
          alert('b');
      }
      zns.color.getUser=function(){
          alert('c');
      }
      zns.common.getUser();
      zns.ms.getUser();
      zns.color.getUser();

3.js中的引用问题:(函数不会出现js引用问题)
    当把arr1给arr2时,计算机为了节约空间,会把arr1与arr2同时指向一个内存空间
    而不是复制一份再赋给arr2,所以当改变arr2时,arr1也会发生改变,这个就叫js引用
     var arr1=[1,2,3];
     var arr2=arr1;
     arr2.push(4);
     alert(arr1);    //1,2,3,4
     alert(arr2);    //1,2,3,4

    ==>解决js引用问题:
    将arr2定义为一个空数组,这时arr1与arr2指向不同的内存空间
     var arr1=[1,2,3];
     var arr2=[];
     for(var i=0;i<arr1.length;i++){
         arr2.push(arr[i]);
     }
     arr2.push(4);
     alert(arr1);    //1,2,3
     alert(arr2);    //1,2,3,4


JS面向对象的继承:
1.通过call让B继承A的属性
2.通过B.prototype=A.prototype让B继承A的方法(会出现js引用问题)
  解决A,B之间引用问题--通过for-in循环
  for(var i in A.prototype){
        B.prototype[i]=A.prototype[i];
    }
3.继承详解:
    function A(){
        this.abc=12;
    }
    A.prototype.show=function(){
        alert(this.abc);
    }
    //继承A
    function B(){
        //this-->new B
        A.call(this);    //本来给A添加属性,现在通过call改变A中的this,变成给B添加属性
    }
    B.prototype=A.prototype;    //继承A的方法,但会出现js引用问题,让A和B同时指向一个内存空间
    B.prototype.fn=function(){  //给子类B新添加属于自己独有的方法
        alert('dec');
    }
    var objB=new B();
    var objA=new A();
    alert(objB.abc);    //12
    objB.show();        //12
    objB.fn();    //dec
    objA.fn();    //dec,这时子类B对象上的方法同样出现在A对象上面,而A对象不应该有,出现问题,是因为js引用的问题

    //解决A,B之间引用问题-->通过for-in循环
    JS继承最终代码:

    function A(){
        this.abc=12;
    }
    A.prototype.show=function(){
        alert(this.abc);
    }
    //继承A
    function B(){
        //this-->new B
        A.call(this);    //本来给A添加属性,现在通过call改变A中的this,变成给B添加属性
    }
    //B.prototype=A.prototype;    //会出现js引用问题,让A和B同时指向一个内存空间
    for(var i in A.prototype){
        B.prototype[i]=A.prototype[i];
    }
  B.prototype.fn=function(){
        alert('abc');
    }
    var objB=new B();
    var objA=new A();
    alert(objB.abc);    //12
    objB.show();        //12
    objB.fn();    //abc
    //objA.fn();    --这时再写这句话就会报错,所以应该去掉,因为A没有fn这个方法才是正确的

 继承例子:
     继承父类的拖拽,实现子类有限制范围的拖拽

<style media="screen">
    #parentDiv{
       350px;
      height: 350px;
      background: #ccc;
      position: relative;
    }
    #div1{
       150px;
      height: 150px;
      background: red;
      position: absolute;
    }
    #div2{
       100px;
      height: 100px;
      background: blue;
      position: absolute;
    }
  </style>


<div id="parentDiv">
    <div id="div1">父类拖拽</div>
    <div id="div2">子类限制范围继承拖拽</div>
 </div>


<script type="text/javascript">
    window.onload=function(){
      var dragDiv=new Drag('div1');
      var limitDrag=new LimitDrag('div2');
    }
    //父类面向对象的拖拽
    function Drag(id){
      var _this=this;
      this.disX=0;
      this.disY=0;
      this.oDiv=document.getElementById(id);
      this.oDiv.onmousedown=function(ev){
        _this.mouseDown(ev);
        return false;
      };
    }
    Drag.prototype.mouseDown=function(ev){
      var _this=this;
      var oEvent=ev||event;
      this.disX=oEvent.clientX-this.oDiv.offsetLeft;
      this.disY=oEvent.clientY-this.oDiv.offsetTop;
      document.onmousemove=function(ev){
        _this.mouseMove(ev);
        return false;   //阻止拖动过程中选中文字的默认行为
      };
      document.onmouseup=function(){
        _this.mouseUp();
      };
    }

    Drag.prototype.mouseMove=function(ev){
      var oEvent=ev||event;
      this.oDiv.style.left=oEvent.clientX-this.disX+'px';
      this.oDiv.style.top=oEvent.clientY-this.disY+'px';
    }
    Drag.prototype.mouseUp=function(){
      document.onmousemove=null;
      document.onmouseup=null;
    }

    //子类继承父类实现有限制范围的拖拽
    //1.继承父类的属性
    function LimitDrag(id){
      Drag.call(this,id);
    }
    //2.继承父类的方法
    for(var i in Drag.prototype){
      LimitDrag.prototype[i]=Drag.prototype[i];
    }
    //3.重写,将子类与父类不同的地方进行重写
    //(子类从父类那里已经继承一个mouseMove,这时重写将把原来的覆盖)
    LimitDrag.prototype.mouseMove=function(ev){
      var oEvent=ev||event;
      var parentDiv=document.getElementById('parentDiv');
      var l=oEvent.clientX-this.disX;
      var t=oEvent.clientY-this.disY;
      if (l<0) {
        l=0;
      }else if(l>parentDiv.offsetWidth-this.oDiv.offsetWidth){
        l=parentDiv.offsetWidth-this.oDiv.offsetWidth;
      }
      if (t<0) {
        t=0;
      }else if(t>parentDiv.offsetHeight-this.oDiv.offsetHeight){
        t=parentDiv.offsetHeight-this.oDiv.offsetHeight;
      }
      this.oDiv.style.left=l+'px';
      this.oDiv.style.top=t+'px';
    }
  </script>

3.系统对象:(js里面的对象)
    1)本地对象(非静态对象)
        --需要经过实例化(new)的对象,才可以使用==>var arr=new Array();    arr.search();
        --常用对象:Object,Function,Array,String,Boolean,Number,Date,RegExp,Error
    2)内置对象(静态对象)
        --不需要经过实例化(new)的对象,直接可以使用==>Math.ceil();
        --常用:Global,Math
    3)宿主对象(由浏览器提供的对象)
        --对于JS的宿主,就是js的运行环境,一般指浏览器DOM,BOM
        --宿主对象随着js运行环境的不同而不同(而1,2与js运行环境无关),
        --如node中在后台编写代码,他就有新的js对象

原文地址:https://www.cnblogs.com/yufann/p/JS-Summary5.html