面试的时候, 总会被问到, 你对 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;
- }
- }
来源: https://www.cnblogs.com/chengxs/p/9297286.html