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;
    }
}

 

posted @ 2018-07-14 23:17  saucxs  阅读(824)  评论(0编辑  收藏  举报