ES5面向对象的类、原型、继承

类和原型

    • 类(Class)是对某种类型的对象定义变量和方法的原型。
    • 它表示对现实生活中一类具有共同特征的事物的抽象,是面向对象编程的基础。
    • 类是对象的抽象
  • 对象

    • 对象是类的实例化
  • ES5的面向对象

    • 没有类的概念
    • 函数是对象,可以写方法,用函数来模拟类
  • 原型

    • –proto–是函数基于对象的原理

    • prototype,是函数独有的属性——原型

      • 包含constructor和–proto–
        • constructor与当前函数相同,所以当前函数可以作为构造函数使用
      • Fn.prototype是当前构造函数所属类下面的实例化方法
    • new Fn() 表示实例化构造函数,实例化类

      • 实例化时会将构造函数的prototype对象下的所有方法和属性添加在实例化对象的原型链下

        var f=new Fn();
        console.log(f);
        
      • 类的原型等于实例化对象的原型链

        console.log(Box.prototype===b.__proto__);//true
        
  • 创建类

    function Box(){
    
    }
    
  • 给类的原型上添加方法

    Box.prototype.run=function(){
    
    }
    Box.prototype.play=function(){
                
    }
    
  • 给类的构造函数上添加方法

    Box.run=function(){
    
    }
    
  • 一类所有的实例化对象增加方法

    var div0=document.querySelector(".div0");
    var div1=document.querySelector(".div1");
    HTMLDivElement.prototype.setBg=function(){
        this.style.width="50px";
        this.style.height="50px";
        this.style.border="1px solid #000000";
        this.style.backgroundColor="red";
    }
    div0.setBg();
    div1.setBg();
    
  • 给某一类所有的实例化对象增加set/get属性

    • 以拖拽为例
    Object.defineProperties(HTMLDivElement.prototype,{
        _drag:{
            writable:true,
            value:false
        },
        width:{
            set:function(_v){
    			this.style.width=_v.toString().indexOf("px")>-1?_v:_v+"px";
            },
            get:function(){
            	return parseFloat(getComputedStyle(this).width);
            }
        },
    	height:{
            set:function(_v){
    			this.style.height=_v.toString().indexOf("px")>-1?_v:_v+"px";
            },
            get:function(){
            	return parseFloat(getComputedStyle(this).height);
            }
    	},
    	bgColor:{
            set:function(_v){
            	this.style.backgroundColor=(typeof _v === "string")?_v:_v.toString(16).padStart(6,"0");
        	},
        	get:function(){
        		return parseFloat(getComputedStyle(this).backgroundColor);
        	}
        },
        drag:{
            set:function(_v){
                this._drag=_v;
                if(_v){
                    this.style.position="absolute";
                    return this.addEventListener("mousedown",this.dragHandler);
                }
                this.removeEventListener("mousedown",this.dragHandler);
            },
            get:function(){
            	return this._drag;
            }
        },
        dragHandler:{
            value:function(e){
            if(e.type==="mousedown"){
                e.preventDefault();
                document.target=this;
                document.offset={x:e.offsetX,y:e.offsetY};
                document.addEventListener("mousemove",this.dragHandler)
                document.addEventListener("mouseup",this.dragHandler)
            }else if(e.type==="mousemove"){
                this.target.style.left=e.clientX-this.offset.x+"px";
                this.target.style.top=e.clientY-this.offset.y+"px";
            }else if(e.type==="mouseup"){
                document.removeEventListener("mousemove",this.target.dragHandler)
                document.removeEventListener("mouseup",this.target.dragHandler)
            }
            }
        }
    })
    
  • 给数组增加方法

    Array.prototype.some1=function(fn){
        // this是调用该方法的数组
        for(var i=0;i<this.length;i++){
        	if(fn(this[i],i,this)) return true;
        }
        return false;
    }
    
    var arr=[2,4,6];
    var b=arr.some1(function(item,index,arr){
    	return item%2===1;
    })
    console.log(b);
    
  • 将HTMLCollection转换成数组

    var arr=Array.prototype.slice.call(document.querySelectorAll("div"));
    console.log(arr);
    var arr=Array.prototype.concat.apply([],document.querySelectorAll("div"));
    console.log(arr);
    
  • 柯里化

    Function.prototype.currying=function(){
        var arr=[];
        var self=this;
        return function(){
            if(arguments.length>0){
            arr=arr.concat(Array.from(arguments));
            return arguments.callee;
        	}
        	return self.apply(null,arr);
        }
    }
    
    function getSum(){
    	return Array.from(arguments).reduce((value,item)=>value+=item);
    }
    
  • 反柯里化

    • 延迟传参,增加适用范围
    Function.prototype.unCurrying=function(){
        var self=this;
        return function(){
            return Function.prototype.call.apply(self,arguments);
            //arguments=[[1,2,3,4],-4]
    		//push.call.apply(self,arguments)=this.push.call([1,2,3,4],-4)=[1,2,3,4].push(-4)
        }
    }
    
    var push=Array.prototype.push.unCurrying();
    
    function getSum(){
        push(arguments,-4);
        console.log(arguments);
    }
    getSum(1,2,3,4);
    
    • 解决调用uncurrying的函数不确定的问题
      • call.apply()
      • apply.apply()
  • 用原型封装事件解决兼容性问题

    var div=document.querySelector("div");
    
    EventTarget.prototype.on=function(type,handler,bubbles){
        try{
        	this.addEventListener(type,handler,bubbles);
        }catch(e){
        	this.attachqEvent("on"+type,handler);
        }
    }
    
    div.on("click",clickhandler);
        function clickhandler(e){
        console.log("aa");
    }
    

继承

  • ES5的继承

    function Box(){
    
    }
    Box.prototype.a=10;
    
    function Ball(){
    
    }
    Ball.prototype=new Box();
    Object.defineProperty(Ball.prototype,"constructor",{
    	value:Ball
    })
    var c=new Ball();
    console.log(c);
    
    • 在new Box 时已经执行过一次Box,所以无法对被继承的类进行传参

    • 组合式继承

      • 原型链继承
      • 冒充继承
      function Box(v){
          this.v=v;
          console.log(v);
      }
      Box.prototype.run=function(){
      }
      Box.prototype.a=10;
      function Ball(v){
      	Box.call(this,v);//冒充继承
      }
      Ball.prototype=new Box();//原型链继承
      Object.defineProperty(Ball.prototype,"constructor",{
      	value:Ball
      })
      var c=new Ball(3);
      console.log(c);
      
      • Box会执行两次,new Box()时会执行一次,call时会执行一次
    • 寄生式继承

      function Box(v){
          this.v=v;
          console.log(v);
      }
      Box.prototype.run=function(){
      
      }
      Box.prototype.a=10;
      
      function F(){
      
      }
      F.prototype=Box.prototype;
      function Ball(v){
      	Box.call(this,v);
      }
      Ball.prototype=new F();
      Object.defineProperty(Ball.prototype,"constructor",{
      	value:Ball
      })
      var c=new Ball(3);
      console.log(c);
      
      • new Box()时始终都会执行一次Box(),为了不执行Box(),重新定义了一个函数F()将Box的原型赋值给F的原型,所以F的原型与F的原型的引用地址相同,让Ball继承F类,因为F没有函数体,所以什么都不会执行,就不会多执行一次Box的函数体
      • 寄生在F()上
    • 封装寄生式继承

      Function.prototype.extend=function(superClass){
          function F(){};
          F.prototype=superClass.prototype;
          var proto=this.prototype;
          this.prototype=new F();
          var names=Object.getOwnPropertyNames(proto);
          for(var i=0;i<names.length;i++){
              var desc=Object.getOwnPropertyDescriptor(proto,names[i]);
              Object.defineProperty(this.prototype,names[i],desc);
          }
          Object.defineProperty(this.prototype,"constructor",{
          	value:this
          });
          this.prototype.superClass=superClass;
          if(superClass.prototype.constructor!==superClass){
              Object.defineProperty(superClass.prototype,"constructor",{
              value:superClass,
              });
          }
      }
      
      function Box(v){
          this.v=v;
          console.log(v);
      }
      
      Box.prototype.run=function(){
      	console.log("a");
      }
      Box.prototype.a=10;
      
      function Ball(v){
      	this.superClass.apply(this,arguments);
      }
      Ball.extend(Box);
      Ball.prototype.run=function(){
          this.superClass.prototype.run.apply(this,arguments);
          console.log("b");
      }
      var c=new Ball(5);
      console.log(c);
      c.run()
      

设计模式

  • 共23种模式,分为3大类
    • 创建型模式
      • 单例模式
      • 抽象工厂模式
      • 建造者模式
      • 工厂模式
      • 原型模式
    • 结构型模式
      • 适配器模式
      • 桥接模式
      • 装饰模式
      • 组合模式
      • 外观模式
      • 享元模式
      • 代理模式
    • 行为型模式
      • 模板方法模式
      • 命令模式
      • 迭代器模式
      • 观察者模式
      • 中介者模式
      • 备忘录模式
      • 解释器模式
      • 状态模式
      • 策略模式
      • 职责链模式
      • 访问者模式
  • 工厂模式
    • 定义一个用于创建对象的接口,让子类决定实例化哪一个类
    • 根据传入的不同数据,创建不同的类,
  • 单例模式
    • 最后只创造唯一的对象
    • 优点
      • 可以用来划分命名空间,减少全局变量的数量
      • 使用单例模式可以是代码组织的更为一致,使代码容易阅读和维护
      • 可以被实例化,且实例化一次
  • Proxy对象--------代理模式
    • 把对一个对象的访问交给另一个代理对象来操作
  • 观察者模式
    • 一个被称为被观察者的对象,维护一组被称为观察者的对象,这些对象依赖于被观察者,被观察者自动将自身的状态的任何变化通知给他们。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值