浅谈Javascript面向对象编程


Posted in Javascript onNovember 15, 2011

在JS中充分使用面向对象设计思想,可以极大限度的提升代码重用、降低模块间的偶合、更好的逻辑分层与并行开发。下面分几个步骤简单谈下我的理解。

一、数据类型与包装类

包装类 …… 类型名 …… 常见值 …… 分类

Number …… number …… 123.123 …… 基本数据类型

Boolean …… Boolean …… true、false …… 基本数据类型

String …… string …… “hello world!” …… 基本数据类型

Object …… object …… {}、[] …… 复合数据类型

Function …… function …… function(){} …… 特殊类型

无 …… undefined …… undefined、未定义 …… 小数据类型

无 …… null …… null …… 小数据类型

内置类型与本文关系不大,不列出。

二、引用类型与值类型

引用类型:object function

值类型:number、boolean、string、null、undefined

三、new function(构造器)与prototype(原型)

关于prototype的设计模式就不多说了,网上很多介绍,以一个例子介绍一下js中使用new构造对象的过程。

function classname(){this.id=0;} var v=new classname();

当使用function构造对象时,进行以下流程:

1、 查找classname的prototype,并进行浅拷贝。

2、 绑定this指针到拷贝来的对象。

3、 将this.constructor属性设置为classname。

[注:其实classname.prototype.constructor的值也被设置为classname,第六部分会说明]

4、 执行用户{}中的代码。

5、 返回this指针赋予左值v。

四、实现面向对象的三个基本特征

1、 封装

封装这个大家都明白,在js中,重点在于访问权限。在其他原生支持面向对象语言中,一般支持public、protected、private三个关键字来控制访问权限,但在js中,我们只能依靠复杂的作用域关系来控制:

function classname(a){ var uid=a; //uin为模拟private,作用域为{},外部无法使用 
this.getuid=function(){return a;} //为uid提供一个外部只读接口 obj.getuid(); 
this.setuid=function(val){a=val} //为uid提供一个外部可写接口obj.setuid(5); 
this.id=uid; //id为模拟public obj.id 使用 
} 
classname.prototype.func=function(){}; //模拟public方法 obj.func()调用 
classname.stafunc=function(){}; //模拟静态方法 classname.stafunc()调用 
var obj=new classname(1);

[!]非常需要注意的就是,因为function是引用类型, classname.prototype.func是所有对象共享的一个function对象(每个对象仅存着引用),因此对象规模不大。而使用this.getuid和this.setuid为定义一个function,因此每个对象实例都会存一份,如果放肆使用这种方法,会造成对象规模庞大,影响性能。个人认为模拟private变量的意义不大。

[!]如果有需求真的需要大量使用this.xxx=function(){}这种情况,在function(){}中的this指针与最外的this指针是不同的,最好在类定义的首行加上var _this=this;,这样在this.xxx=function(){}中也可以方便使用绑定的指针。

2、 继承

继承的实现,主要有2种方法:第一种是使用javascript本身的原型模型,通过给prototype赋值并改变其constructor属性来实现继承;第二种方法是不使用prototype,手动实现将父对象的所有属性方法深拷贝到子对象。比如A需要继承B,第一种写法可以:A.prototype=new B();A.prototype.constructor=A; 第二种写法可以写一个递归,或者使用jquery中的方法extend。另外,如果要实现多继承的话,prototype就真的好麻烦了(需要依次多个类,还要建空对象来接),第二种方法就比较简单,依次拷贝即可。一般这种继承为了找父类方便,可以在对象中加个属性,引用父类。

3、 多态

函数重载就不说了,都会,检查参数即可,很灵活。隐藏属性就是直接赋值undefined。需要注意的是,如果是打算继承B类的prototype,一定要建一个空对象来接,否则的话,你给类写方法的话,相当于直接修改了prototype,就算不写方法,你最后修改constructor时也会造成继承链错乱,接个空对象很容易:

function temp(){}; temp.prototype=B; 
var obj=new temp();

这样再让需要继承B.prototype的类继承obj即可,即便修改prototype也不会影响到B。而且也不像继承new B()那样浪费很多空间。

五、深拷贝与浅拷贝

这个和其他语言中没什么区别,浅拷贝就是直接拷贝,遇到引用类型或类类型不再深入。深拷贝则是根据类型判断,进行递归拷贝。

六、prototype.constructor

这个值主要是用于维护继承的原型链。一篇文章已经写的非常详细,请参考:http://bbs.51js.com/thread-84148-1-1.html

七、JS的面向对象开发

由于我不是前台开发人员,见过项目有限,仅谈自己的经验。

我开发过的B/S,常用两种架构,一种是以CGI为主,由后台语言去生成HTML,JS仅仅做一些用户交互,ajax通信等。另外一种是使用MVC,后台语言仅仅生成JSON,View层完全由JS组件在客户端实现。后者一般大量使用面向对象的思想进行编程,将组件封装成类,将JSON传入构造函数,再由控制器或布局组件Add进来。由于组件可以重用,在开发后台管理系统、JS游戏上,效率还是很可观的。

Javascript 相关文章推荐
javascript 字符 Escape,encodeURI,encodeURIComponent
Jul 09 Javascript
javascript 获取页面的高度及滚动条的位置的代码
May 06 Javascript
用JS判别浏览器种类以及IE版本的几种方法小结
Aug 02 Javascript
jQuery语法高亮插件支持各种程序源代码语法着色加亮
Apr 27 Javascript
JS实现鼠标单击与双击事件共存
Mar 08 Javascript
BootStrap创建响应式导航条实例代码
May 31 Javascript
用js控件div的滚动条,让它在内容更新时自动滚到底部的实现方法
Oct 27 Javascript
JS高仿抛物线加入购物车特效实现代码
Feb 20 Javascript
基于vue实现多引擎搜索及关键字提示
Mar 16 Javascript
详解webpack-dev-server 设置反向代理解决跨域问题
Apr 18 Javascript
Angular6 发送手机验证码按钮倒计时效果实现方法
Jan 08 Javascript
Vue render函数实战之实现tabs选项卡组件
Apr 22 Javascript
js Html结构转字符串形式显示代码
Nov 15 #Javascript
Js 时间间隔计算的函数(间隔天数)
Nov 15 #Javascript
jQuery源码分析-05异步队列 Deferred 使用介绍
Nov 14 #Javascript
jQuery源码分析-04 选择器-Sizzle-工作原理分析
Nov 14 #Javascript
jQuery源码分析-03构造jQuery对象-工具函数
Nov 14 #Javascript
jQuery源码分析-03构造jQuery对象-源码结构和核心函数
Nov 14 #Javascript
jQuery源码分析-02正则表达式 RegExp 常用正则表达式
Nov 14 #Javascript
You might like
一周让你学会PHP 不错的学习资料
2009/02/06 PHP
PHP数据类型之整数类型、浮点数的介绍
2013/04/28 PHP
解析PHP中的正则表达式以及模式匹配
2013/06/19 PHP
PHP动态编译出现Cannot find autoconf的解决方法
2014/11/05 PHP
浅谈laravel-admin的sortable和orderby使用问题
2019/10/03 PHP
基于JavaScript实现继承机制之调用call()与apply()的方法详解
2013/05/07 Javascript
JSP中使用JavaScript动态插入删除输入框实现代码
2014/06/13 Javascript
jQuery实现购物车数字加减效果
2015/03/14 Javascript
AngularJS 中文API参考手册
2016/07/28 Javascript
Angular.JS学习之依赖注入$injector详析
2016/10/20 Javascript
使用Ajax生成的Excel文件并下载的实例
2016/11/21 Javascript
jQuery滚动监听实现商城楼梯式导航效果
2017/03/06 Javascript
Javascript中字符串相关常用的使用方法总结
2017/03/13 Javascript
js+html获取系统当前时间
2017/11/10 Javascript
javascript代码优化的8点总结
2018/01/29 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
jQuery常见的遍历DOM操作详解
2018/09/05 jQuery
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
2019/09/05 Javascript
JS数组属性去重并校验重复数据
2020/01/10 Javascript
ajax jquery实现页面某一个div的刷新效果
2021/03/04 jQuery
通过mod_python配置运行在Apache上的Django框架
2015/07/22 Python
Python编程产生非均匀随机数的几种方法代码分享
2017/12/13 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
2018/01/04 Python
Python基于Floyd算法求解最短路径距离问题实例详解
2018/05/16 Python
详解用python生成随机数的几种方法
2019/08/04 Python
python dumps和loads区别详解
2020/02/04 Python
python 遗传算法求函数极值的实现代码
2020/02/11 Python
使用pymysql查询数据库,把结果保存为列表并获取指定元素下标实例
2020/05/15 Python
python 在sql语句中使用%s,%d,%f说明
2020/06/06 Python
关于Theano和Tensorflow多GPU使用问题
2020/06/19 Python
解决Pycharm双击图标启动不了的问题(JetBrains全家桶通用)
2020/08/07 Python
python 制作简单的音乐播放器
2020/11/25 Python
荷兰本土平价百货:HEMA
2017/10/23 全球购物
如何将整数int转换成字串String
2014/03/21 面试题
销售经理岗位职责范本
2015/04/02 职场文书
排查并解决Oracle sysaux表空间异常增长
2022/04/20 Oracle