我们通过表单验证的功能,来逐步演进面向对象的方式.   对于刚刚接触javascript的朋友来说,如果要写一个验证用户名,密码,邮箱的功能, 一般可能会这么写:

         //表单验证
var checkUserName = function(){
console.log( '全局checkUserName' );
};
var checkUserEmail = function(){
console.log( '全局checkUserEmail' );
};
var checkUserPwd = function(){
console.log( '全局checkUserPwd' );
};

这种写法,从功能上来说 没有什么问题, 但是在团队协作的时候, 会造成覆盖全局变量的问题, 那要大大降低覆盖的可能性, 一般会在外面套一个对象

         var Utils = {
checkUserName : function(){
console.log( 'Utils->checkUserName' );
},
checkUserEmail : function(){
console.log( 'Utils->checkUserEmail' );
},
checkUserPwd : function(){
console.log( 'Utils->checkUserPwd' );
}
} checkUserEmail();
Utils.checkUserEmail();

上面这种方式,是字面量方式添加,在设计模式里面,也称为单例(单体)模式, 与之类似的可以通过在函数本身添加属性和方法,变成静态属性和方法,达到类似的效果:

         var Utils = function(){

         }
Utils.checkUserName = function(){
console.log( 'Utils.checkUserName' );
}
Utils.checkUserPwd = function(){
console.log( 'Utils.checkUserPwd' );
}
Utils.checkUserEmail = function(){
console.log( 'Utils.checkUserEmail' );
} Utils.checkUserEmail(); for( var key in Utils ){
( Utils.hasOwnProperty( key ) ) ? console.log( key ) : '';
} //加在函数上面的属性和方法,无法通过对象使用
var oUtil = new Utils();
oUtil.checkUserEmail();//错误

还可以通过函数调用方式,返回一个对象,把方法和属性写在对象中, 这种方式 跟面向对象没有什么关系,只是从函数的返回值角度来改造

         //使用函数的方式 返回一个对象
var Util = function(){
return {
checkUserName : function(){
console.log( 'userName...' );
},
checkUserPwd : function(){
console.log( 'userPwd...' );
},
checkUserEmail : function(){
console.log( 'userEmail...' );
}
}
}
Util().checkUserEmail();

还可以通过类似传统面向对象语言,使用构造函数方式 为每个实例添加方法和属性, 这种方式,存在一个问题, 不能达到函数共用,每个实例都会复制到方法.

         var Util = function(){
this.checkUserName = function(){
console.log('userName');
};
this.checkUserEmail = function(){
console.log('userEmail');
};
this.checkUserPwd = function(){
console.log('userPwd');
};
} var oUtil1 = new Util();
var oUtil2 = new Util();
console.log( oUtil1.checkUserEmail === oUtil2.checkUserEmail );//false

一般,我们可以通过原型属性(prototype)改造这种方式,达到不同实例共用同一个方法

         var Util = function(){

         };
Util.prototype.checkUserName = function(){
console.log('userName');
};
Util.prototype.checkUserPwd = function(){
console.log('userPwd');
};
Util.prototype.checkUserEmail = function(){
console.log('userEmail');
};
var oUtil1 = new Util();
var oUtil2 = new Util();
console.log( oUtil1.checkUserEmail === oUtil2.checkUserEmail );//true

也可以把原型对象上的所有方法,使用字面量方式简写

         var Util = function(){

         };
Util.prototype = {
checkUserEmail : function(){
console.log( 'userEmail' );
},
checkUserName : function(){
console.log( 'userName' );
},
checkUserPwd : function(){
console.log( 'userPwd' );
}
};
var oUtil1 = new Util();
var oUtil2 = new Util();
console.log( oUtil1.checkUserEmail === oUtil2.checkUserEmail );//true

注意:  字面量方式和原型对象一个个添加   这两种不要混用, 否则会产生覆盖

如果我们想把面向对象的使用方式更加的优雅,比如链式调用, 我们应该在每个方法中返回对象本身,才能继续调用方法, 即返回this

         var Util = function(){
return {
checkUserName : function(){
console.log( 'userName...' );
return this;
},
checkUserPwd : function(){
console.log( 'userPwd...' );
return this;
},
checkUserEmail : function(){
console.log( 'userEmail...' );
return this;
}
}
}
// 方法中如果没有返回this,下面这种调用方式是错误的
Util().checkUserEmail().checkUserName(); // 方法中返回对象本身,可以链式调用
Util().checkUserEmail().checkUserName().checkUserPwd();
         var Util = function(){
this.checkUserName = function(){
console.log('userName');
return this;
};
this.checkUserEmail = function(){
console.log('userEmail');
return this;
};
this.checkUserPwd = function(){
console.log('userPwd');
return this;
};
} new Util().checkUserEmail().checkUserName().checkUserPwd();
        var Util = function(){

        };
Util.prototype = {
checkUserEmail : function(){
console.log( 'userEmail' );
return this;
},
checkUserName : function(){
console.log( 'userName' );
return this;
},
checkUserPwd : function(){
console.log( 'userPwd' );
return this;
}
}; new Util().checkUserEmail().checkUserName().checkUserPwd();
         var Util = function(){

         };
Util.prototype.checkUserName = function(){
console.log('userName');
return this;
};
Util.prototype.checkUserPwd = function(){
console.log('userPwd');
return this;
};
Util.prototype.checkUserEmail = function(){
console.log('userEmail');
return this;
}; new Util().checkUserEmail().checkUserName().checkUserPwd();

在实际开发中,我们经常需要扩展一些功能和模块。扩展可以在本对象或者父类对象或者原型上

         Function.prototype.checkUserName = function(){
console.log('ghostwu');
}; var fn1 = function(){};
var fn2 = function(){}; console.log( 'checkUserName' in fn1 ); //true
console.log( 'checkUserName' in fn2 ); //true fn1.checkUserName(); //ghostwu
fn2.checkUserName(); //ghostwu

如果我们使用上面这种方式扩展,从功能上来说,是没有问题的,但是确造成了全局污染:通俗点说,并不是说有的函数都需要checkUserName这个方法,而我们这样写,所有的函数在创建过程中都会从父类的原型链上继承checkUserName, 但是这个方法,我们根本不用, 所以浪费性能, 为了解决这个问题,我们应该要在需要使用这个方法的函数上添加,不是所有的都添加,另外关于in的用法,如果不熟悉,可以看下我的这篇文章:立即表达式的多种写法与注意点以及in操作符的作用

         Function.prototype.addMethod = function( name, fn ){
this[name] = fn;
} var fn1 = function(){};
var fn2 = function(){}; fn1.addMethod( 'checkUserName', function(){console.log('ghostwu');}); fn1.checkUserName(); //ghostwu
fn2.checkUserName(); //报错

通过上述的改造,成功解决了全局污染, fn2这个函数上面没有添加checkUserName这个方法,只在fn1上面添加

我们继续把上面的方式,改成链式调用:  这里需要改两个地方, 一种是添加方法addMethod可以链式添加, 一种是添加完了之后,可以链式调用

         Function.prototype.addMethod = function( name, fn ){
this[name] = fn;
return this;
}; var fn1 = function(){}; fn1.addMethod( 'checkUserName', function(){
console.log( 'userName:ghostwu' );
return this;
} ).addMethod( 'checkUserEmail', function(){
console.log( 'userEmail' );
return this;
} ).addMethod( 'checkUserPwd', function(){
console.log( 'userUserPwd' );
return this;
} );
fn1.checkUserName().checkUserEmail().checkUserPwd();

上面是属于函数式 链式 调用,  我们可以改造addMethod方法, 在原型上添加函数,而不是实例上, 这样我们就可以达到类式的链式调用

         Function.prototype.addMethod = function( name, fn ){
this.prototype[name] = fn;
return this;
}; var fn1 = function(){}; fn1.addMethod( 'checkUserName', function(){
console.log( 'userName:ghostwu' );
return this;
} ).addMethod( 'checkUserEmail', function(){
console.log( 'userEmail' );
return this;
} ).addMethod( 'checkUserPwd', function(){
console.log( 'userUserPwd' );
return this;
} );
new fn1().checkUserName().checkUserEmail().checkUserPwd();

javascript面向对象的常见写法与优缺点的更多相关文章

  1. javascript:面向对象和常见内置对象及操作

    本文内容: 面向对象 常见内置对象及操作 首发日期:2018-05-11 面向对象: JavaScript 是面向对象的编程语言 (OOP).OOP 语言使我们有能力定义自己的对象和变量类型. 对象是 ...

  2. javascript面向对象的一些写法

    因为有闭包,能返回函数,所以针对于面向对象的封装,继承,多态三个特性实现,很舒服. 代码如下: <!DOCTYPE html> <html> <head> < ...

  3. javascript面向对象系列第四篇——OOP中的常见概念

    前面的话 面向对象描述了一种代码的组织结构形式——一种在软件中对真实世界中问题领域的建模方法.本文将从理论层面,介绍javascript面向对象程序程序(OOP)中一些常见的概念 对象 所谓对象,本质 ...

  4. javascript面向对象的写法03

    javascript面向对象的写法03 js一些基础知识的说明 prototype 首先每个js函数(类)都有一个prototype的属性,函数是类.注意类有prototype,而普通对象没有. js ...

  5. JavaScript面向对象总结

    对象(Object)应该算是js中最为重要的部分,也是js中非常难懂晦涩的一部分.更是面试以及框架设计中各出没.本文章,主要参考JavaScript红宝书(JavaScript高级程序设计 第六章)以 ...

  6. Javascript面向对象(封装、继承)

    Javascript 面向对象编程(一):封装 作者:阮一峰 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程( ...

  7. JavaScript面向对象简介

    JavaScript面向对象简介 @(编程) [TOC] 1. 命名空间 命名空间是一个容器,它允许开发人员在一个独特的,特定于应用程序的名称下捆绑所有的功能. 在JavaScript中,命名空间只是 ...

  8. 转:javascript面向对象编程

    作者: 阮一峰 日期: 2010年5月17日 学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学 ...

  9. JavaScript面向对象编程[转]

    JavaScript面向对象编程 命名空间 命名空间是一个容器,它允许开发人员在一个独特的,特定于应用程序的名称下捆绑所有的功能. 在JavaScript中,命名空间只是另一个包含方法,属性,对象的对 ...

随机推荐

  1. C++实现-特征码遍历

    #include <stdio.h> #include <stdlib.h> #include <windows.h> union Base { DWORD add ...

  2. tenda某路由器信息泄露查找

    本文作者:i春秋作家——icqb32d3a26 1: 前期准备: (1) 路由器固件 一般获取固件的方法有以下几种 官方网站根据对应版本下载(√),点击下载 在点击更新固件时抓取对应的更新固件链接 拆 ...

  3. objc_msgSend 作用

    C 的函数调用方式 C 语言使用静态绑定,即在编译器就可以决定运行时所应调用的函数. 编译器在编译代码的时候就已经知道程序中有相应的函数,并直接生成调用函数的指令.函数地址硬编码在指令之中. OC 中 ...

  4. SQL 高效的万能分页存储过程

    代码如下: USE [Blog] IF OBJECT_ID('Proc_Paging', 'P') IS NOT NULL --删除同名存储过程 DROP PROC Proc_Paging GO CR ...

  5. iOS开发总结——协议代理的认识

    1.前言 自今年5月底正式转iOS之后,天天get新技能,很多技能在脑子里回旋不吐不快,所以,写点东西整理一下.先从协议代理开始. 2.协议方法的声明 @protocol EventMenuBarDe ...

  6. Python小白学习之路(十一)—【局部变量和全局变量】【关键字global】【关键字nonlocal】

    写在前面: 几乎有一周没有更新学习笔记了吧 上周一周身体都不怎么舒服 然后还得写开题报告 然后还得看文献 天天就是写写写写写写~~~~~~改改改改改改~~~~~~~~~ 今天又开始学习了 希望之前的没 ...

  7. 课程一(Neural Networks and Deep Learning),第一周(Introduction to Deep Learning)—— 1、经常提及的问题

    Frequently Asked Questions Congratulations to be part of the first class of the Deep Learning Specia ...

  8. 【Java】认识 JDK,JRE,JVM

    JDK,JRE,JVM 今天我们讨论下这三个Java工具 JDK 全称Java Development ToolKit(Java 开发工具包). JDK是整个JAVA的核心,其包括了Java运行环境( ...

  9. Vue中子组件调用父组件的方法

    Vue中子组件调用父组件的方法 相关Html: <!DOCTYPE html> <html lang="en"> <head> <meta ...

  10. win7安装docker报错:error during connect: Get http ..... the system cannot find the file specified

    因为是win7 所以使用了官方网站的dockertoolbox 安装一路顺利,结果启动就报上面的错误, 因为安装包附带安装了virtualbox 上面的错误后来排查出来是 virtualboox的问题 ...