zoukankan      html  css  js  c++  java
  • javaScript设计模式之面向对象编程(object-oriented programming,OOP)(一)

    面试的时候,总会被问到,你对javascript面向对象的理解?

    面向对象编程(object-oriented programming,OOP)是一种程序设计范型。它讲对象作为程序的设计基本单元,讲程序和数据封装其中,以提高程序的重用性、灵活性和扩展性。

    一、举个例子

    有这么一个需求:做一个验证表单功能,仅需要验证用户名,邮箱,密码等

    觉得在项目产品开发中,自己是这么写的

    function checkName(){
        //验证姓名
    }
    function checkEmail(){
        //验证邮箱
    }
    function checkPassword(){
        //验证码密码
    }

    声明了3个全局变量,

    下面是创建3个函数保存在变量里来实现你的功能,而你写的是将你的变量名放在function后边,也代表了你的变量,所以声明了3个全局变量。

    //创建了3个函数保存在变量里
    var checkName = function(){
        //验证姓名
    }
    var checkEmail = function(){
        //验证码邮箱
    }
    var checkPassword = function(){
        //验证密码
    }

    从功能上讲没有任何问题,但是如果别人也定义了同样的方法就会覆盖原有的功能,这种相互覆盖的问题不易觉察到。

    我们可以将这些检查函数放在一个变量里保存,这样减少覆盖和被覆盖的风险。

    (1)用对象收编变量

    对象,他有属性和方法,我们访问属性或者方法,可以通过点语法向下遍历查询得到,我们可以创建一个检测对象,我们把方法放在里面。

    var CheckObject = {
        checkName:function(){
            //验证姓名
        },
        checkEmail:function(){
            //验证邮箱
        },
        checkPassword:function(){
            //验证密码
        }
    }

    这个时候我们将所有的函数作为CheckObject对象的方法,这样我们就只有一个对象,比如检测姓名CheckObject.checkName().

    (2)对象的另一种形式

    首先声明一个对象,然后给他添加方法,在JavaScript中函数也是对象。

    var CheckObject = function(){};
    CheckObject.checkName = function(){
        //验证姓名
    }
    CheckObject.checkEmail = function(){
        //验证邮箱
    }
    CheckObject.checkPassword = function(){
        //验证密码
    }

    但是当别人想用你写的对象方法就比较麻烦,因为这个对象不能复制一份(这个对象类在用new关键字创建新的对象时,新创建的对象时不能继承这些方法)

    (3)真假对象

    如果想简单的复制一下,你可以将这些方法放在一个函数对象中。

    var CheckObject = function(){
        return {
            checkName = function(){
                //校验姓名
            },
            checkEmail = function(){
                //校验邮箱
            }
            checkPassword = function(){
                //校验密码
            }
        }
    }

    当每次调用这个函数的时候,把我们之前的对象返回出来,当别人每次调用这个函数时都会返回新对象。这样我们每个人使用的时候就不会相互影响,比如检测邮箱可以这样:

    var a = CheckObject();
    a.checkEmail();

    (4)类也可以

    虽然通过创建新对象完成需求,但是他不是一个真正的意义上的类的创建方式,并且创建对象a和对象CheckObject没有任何关系,返回的对象与CheckObject对象无关,稍微优化一下。

    var CheckObject = function(){
        this.checkName = function(){
            //验证姓名
        }
        this.checkEmail = function(){
            //验证邮箱
        }
        this.checkPassword = function(){
            //验证密码
        }
    }

    上面的这样的对象,就可以看成是类,我们就可以不需要使用创建对象方法创建,既然是一个类,就用关键词new来创建

    var a = new CheckObject();
    a.checkEmail();

    这样就可以用CheckObject类创建出来对象,我们其他人就可以对类实例化(用类创建对象),这样每一个人都有一套自己的方法。

    (5)一个检测类

    通过this的定义,每一次通过new关键字创建新对象时候,新创建的对象都会对类的this上的属性进行复制,所以新创建的对象都会有自己的一套方法,然而有时候造成消耗很奢侈,我们需要处理一下。

    var CheckObject = function(){};
    CheckObject.prototype.checkName = function(){
        //验证姓名
    }
    CheckObject.prototype.checkEmail = function(){
        //验证邮箱
    }
    CheckObject.prototype.checkPassword = function(){
        //验证密码
    }

    这样创建对象实例时候,创建出来的对象所拥有的方法都是一个,因为他们需要依赖prototype原型依次寻找,而找到方法是同一个,但是prototype写很多遍,可以这么写

    var CheckObject = function(){};
    checkObject.prototype = {
        checkName:function(){
            //验证姓名
        },
        checkEmail:function(){
            //验证邮箱
        },
        checkPassword:function(){
        //验证密码
        }
    }

    以上两种方法不能混着用。

    如在后边为对象的原型对象赋值新对象,那么会覆盖之前对prototype对象赋值的方法。

    var  a  = new CheckObject();
    a.checkName();
    a.checkEmail();
    a.checkPassword();

    (6)方法还可以这样用

    1、this对象

    var CheckObject = {
        checkName:function(){
        //验证姓名
        return this;
        },
        checkEmail:function(){
        //验证邮箱
        return this;
        },
        checkPassword:function(){
        //验证密码
        return this;
        }
    }

    使用:

    CheckObject.checkName().checkEmail().checkPassword();

    2、类的原型对象

    var CheckObject = function(){};
    CheckObject.prototype = {
        checkName:function(){
        //验证姓名
        return this;
        },
        checkEmail:function(){
        //验证邮箱
        return this;
        },
        checkPassword:function(){
        //验证密码
        return this;
        }
    }

    但是使用的时候需要创建一下

    var a = new CheckObject();
    a.checkName().checkEmail().checkPassword();

    (7)函数祖先

    比如你想给每一个函数都添加一个检测邮箱的方法。

    Function.prototype.checkEmail = function(){
        //检测邮箱

    这样使用这个方法就比较简单,

    1、函数形式

    var f = function(){};
    f.checkEmail();

    2、类的形式

    var f = new Function();
    f.checkEmail();

    你这种方式,原则上没有问题,但是污染了全局原生对象Function,这样别人创建的函数也会被你创建的函数污染,造成不必要的开销,但是你可以抽象出一个统一添加方法的功能方法。方法如下:

    Function.prototype.addMethod = function(name,fn){
        this[name] = fn;
    }

    这个时候,如果你想添加邮箱验证的方法和姓名验证的方法,可以这样使用

    var methods = function(){};
    //或者
    var methods = new Function();
    methods.addMethod('checkName',function(){
      //验证姓名
    })
    methods.addMethod('checkEmail',function(){
      //验证邮箱
    })
    methods.checkName();
    methods.checkEmail();

    (8)链式添加

    如果想链式添加,在addMethods中将this返回,就可以

    Function.prototype.addMethod = function(name,fn){
        this[name] = fn;
        return this;
    }

    如果你还想添加方法,可以这样:

    var methods = function(){};
    methods.addMethod('checkName',function(){
       //验证姓名 
    }).addMethod('checkEmail',function(){
       //验证邮箱 
    });

    如果我想链式使用,应该如何实现?

    既然添加方法可以将this返回实现,那么添加的每一个方法都将this返回是不是也就实现了呢?

    var methods = function(){};
    methods.addMethod('checkName',function(){
       //验证姓名
       return this;  
    }).addMethod('checkEmail',function(){
       //验证邮箱
       return this;  
    })

    测试一下:

    methods.checkName().checkEmail();

    (9)换一种使用方式

    1、函数式调用

    Function.prototype.addMethod = function(name,fn){
        this[name] = fn;
        return this;
    }

    2、类式调用

    Function.prototype.addMethod = function(name,fn){
        this.prototype[name] = fn;
        return this;
    }

    使用类式调用,不能直接使用,需要通过new关键字来创建新对象

    var m = new Methods();
    m.checkEmail();

    JavaScript中函数时一等公民。

    1、如何实现方法的链式调用?

    只需在类中的每个方法中通过this关键字返回对象实例的引用。每次函数调用都会返回一个新对象,表面上是CheckObject对象,实际是返回的新对象,这样每次调用就不会相互影响了。

    2、为函数添加多个方法的addMethod方法?

    (1)this对象

    var CheckObject = {
         checkName: function(){
          //验证姓名
          return this;      
        } ,   
       checkEmail: function(){
          //验证邮箱
          return this;      
        } ,  
       checkPassword: function(){
          //验证密码
          return this;      
        } ,  
    }

    (2)类的原型对象

    var CheckObject = function(){};
    CheckObject.prototype = {
         checkName:function(){
         //验证姓名
         return this;
        } ,
        checkEmail:function(){
         //验证邮箱
         return this;
         },
         checkPassword:function(){
         //验证密码
         return this;
        }
    }
  • 相关阅读:
    DIJ最短路
    快速输入/输出
    Codeforces Round #610 (Div. 2).K for the Price of One (Hard Version)
    Codeforces Round #625 (Div. 1, based on Technocup 2020 Final Round).B. Navigation System
    Codeforces Round #612 (Div. 2)C. Garland
    Codeforces Round #621 (Div. 1 + Div. 2).D. Cow and Fields
    73.Python中ORM聚合函数详解:Count
    72.Python中ORM聚合函数详解:Avg,aggregate,annotate
    17. Getting to the essence of things
    55.ORM外键:引用同app下的不同模型,引用不同app下的模型,引用模型自身使用详解
  • 原文地址:https://www.cnblogs.com/chengxs/p/9297286.html
Copyright © 2011-2022 走看看