Javascript定义类(class)的三种方法详解


Posted in Javascript onMarch 13, 2015

将近20年前,Javascript诞生的时候,只是一种简单的网页脚本语言。如果你忘了填写用户名,它就跳出一个警告。

Javascript定义类(class)的三种方法详解

如今,它变得几乎无所不能,从前端到后端,有着各种匪夷所思的用途。程序员用它完成越来越庞大的项目。

Javascript代码的复杂度也直线上升。单个网页包含10000行Javascript代码,早就司空见惯。2010年,一个工程师透露,Gmail的代码长度是443000行!

Javascript定义类(class)的三种方法详解

编写和维护如此复杂的代码,必须使用模块化策略。目前,业界的主流做法是采用"面向对象编程"。因此,Javascript如何实现面向对象编程,就成了一个热门课题。
麻烦的是,Javascipt语法不支持"类"(class),导致传统的面向对象编程方法无法直接使用。程序员们做了很多探索,研究如何用Javascript模拟"类"。本文总结了Javascript定义"类"的三种方法,讨论了每种方法的特点,着重介绍了我眼中的最佳方法。

==============================================

Javascript定义类(class)的三种方法

Javascript定义类(class)的三种方法详解

在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。

Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。

一、构造函数法

这是经典方法,也是教科书必教的方法。它用构造函数模拟"类",在其内部用this关键字指代实例对象。

 function Cat() {

this.name = "大毛";

}

生成实例的时候,使用new关键字。
var cat1 = new Cat();

alert(cat1.name); // 大毛

类的属性和方法,还可以定义在构造函数的prototype对象之上。

Cat.prototype.makeSound = function(){


alert("喵喵喵");

}

关于这种方法的详细介绍,请看我写的系列文章《Javascript 面向对象编程》,这里就不多说了。它的主要缺点是,比较复杂,用到了this和prototype,编写和阅读都很费力。

二、Object.create()法

为了解决"构造函数法"的缺点,更方便地生成对象,Javascript的国际标准ECMAScript第五版(目前通行的是第三版),提出了一个新的方法Object.create()。
用这个方法,"类"就是一个对象,不是函数。

var Cat = {

name: "大毛",


makeSound: function(){ alert("喵喵喵"); }

};

然后,直接用Object.create()生成实例,不需要用到new。

var cat1 = Object.create(Cat);

alert(cat1.name); // 大毛

cat1.makeSound(); // 喵喵喵

目前,各大浏览器的最新版本(包括IE9)都部署了这个方法。如果遇到老式浏览器,可以用下面的代码自行部署。

if (!Object.create) {


Object.create = function (o) {



 function F() {}



F.prototype = o;



return new F();


};

}

这种方法比"构造函数法"简单,但是不能实现私有属性和私有方法,实例对象之间也不能共享数据,对"类"的模拟不够全面。

三、极简主义法

荷兰程序员Gabor de Mooij提出了一种比Object.create()更好的新方法,他称这种方法为"极简主义法"(minimalist approach)。这也是我推荐的方法。

3.1 封装

这种方法不使用this和prototype,代码部署起来非常简单,这大概也是它被叫做"极简主义法"的原因。

首先,它也是用一个对象模拟"类"。在这个类里面,定义一个构造函数createNew(),用来生成实例。

 var Cat = {

createNew: function(){



// some code here


}

};

然后,在createNew()里面,定义一个实例对象,把这个实例对象作为返回值。

 var Cat = {

createNew: function(){



var cat = {};



cat.name = "大毛";



cat.makeSound = function(){ alert("喵喵喵"); };



return cat;


}

};

使用的时候,调用createNew()方法,就可以得到实例对象。

var cat1 = Cat.createNew();

cat1.makeSound(); // 喵喵喵

这种方法的好处是,容易理解,结构清晰优雅,符合传统的"面向对象编程"的构造,因此可以方便地部署下面的特性。

3.2 继承

让一个类继承另一个类,实现起来很方便。只要在前者的createNew()方法中,调用后者的createNew()方法即可。

先定义一个Animal类。

var Animal = {

createNew: function(){



var animal = {};



animal.sleep = function(){ alert("睡懒觉"); };



return animal;


}

};

然后,在Cat的createNew()方法中,调用Animal的createNew()方法。

var Cat = {


createNew: function(){



var cat = Animal.createNew();



cat.name = "大毛";



cat.makeSound = function(){ alert("喵喵喵"); };



return cat;


}

};

这样得到的Cat实例,就会同时继承Cat类和Animal类。
var cat1 = Cat.createNew();

cat1.sleep(); // 睡懒觉

3.3 私有属性和私有方法

在createNew()方法中,只要不是定义在cat对象上的方法和属性,都是私有的。

var Cat = {


createNew: function(){



var cat = {};



var sound = "喵喵喵";



cat.makeSound = function(){ alert(sound); };



return cat;


}

};

上例的内部变量sound,外部无法读取,只有通过cat的公有方法makeSound()来读取。
var cat1 = Cat.createNew();

alert(cat1.sound); // undefined

3.4 数据共享

有时候,我们需要所有实例对象,能够读写同一项内部数据。这个时候,只要把这个内部数据,封装在类对象的里面、createNew()方法的外面即可。

var Cat = {

sound : "喵喵喵",


createNew: function(){



var cat = {};



cat.makeSound = function(){ alert(Cat.sound); };



cat.changeSound = function(x){ Cat.sound = x; };



return cat;


}

};

然后,生成两个实例对象:

var cat1 = Cat.createNew();

var cat2 = Cat.createNew();

cat1.makeSound(); // 喵喵喵

这时,如果有一个实例对象,修改了共享的数据,另一个实例对象也会受到影响。
cat2.changeSound("啦啦啦");

cat1.makeSound(); // 啦啦啦

(完)

Javascript 相关文章推荐
本地对象Array的原型扩展实现代码
Dec 04 Javascript
jQuery ui插件的使用方法代码实例
May 08 Javascript
Javascript中各种trim的实现详细解析
Dec 10 Javascript
基于socket.io和node.js搭建即时通信系统
Jul 30 Javascript
js实现刷新iframe的方法汇总
Apr 27 Javascript
浅析Node.js 中 Stream API 的使用
Oct 23 Javascript
angular route中使用resolve在uglify压缩后问题解决
Sep 21 Javascript
Bootstrap弹出框modal上层的输入框不能获得焦点问题的解决方法
Dec 13 Javascript
WebPack配置vue多页面的技巧
May 15 Javascript
详解easyui 切换主题皮肤
Apr 04 Javascript
javascript操作元素的常见方法小结
Nov 13 Javascript
ES6学习笔记之字符串、数组、对象、函数新增知识点实例分析
Jan 22 Javascript
JavaScript中5种调用函数的方法
Mar 12 #Javascript
JavaScript实现的一个倒计时的类
Mar 12 #Javascript
JavaScript将XML转成JSON的方法
Mar 12 #Javascript
JavaScript中诡异的delete操作符
Mar 12 #Javascript
JavaScript实现计算字符串中出现次数最多的字符和出现的次数
Mar 12 #Javascript
jquery实现页面关键词高亮显示的方法
Mar 12 #Javascript
JavaScript设计模式学习之“类式继承”
Mar 12 #Javascript
You might like
实现dedecms全站URL静态化改造的代码
2007/03/29 PHP
php类常量的使用详解
2013/06/08 PHP
PHP和C#可共用的可逆加密算法详解
2015/10/26 PHP
学习php设计模式 php实现享元模式(flyweight)
2015/12/07 PHP
jQeury淡入淡出需要注意的问题
2010/09/08 Javascript
js下通过getList函数实现分页效果的代码
2010/09/17 Javascript
intro.js 页面引导简单用法 分享
2013/08/06 Javascript
js/jQuery简单实现选项卡功能
2014/01/02 Javascript
php和js对数据库图片进行等比缩放示例
2014/04/28 Javascript
gulp-htmlmin压缩html的gulp插件实例代码
2016/06/06 Javascript
jquery插件bootstrapValidator数据验证详解
2016/11/09 Javascript
浅谈AngularJS中ng-class的使用方法
2016/11/11 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
2017/03/28 Javascript
bootstrap switch开关组件使用方法详解
2017/08/22 Javascript
微信小程序实现自定义modal弹窗封装的方法
2018/06/15 Javascript
Node.js对MongoDB进行增删改查操作的实例代码
2019/04/18 Javascript
js实现无缝滚动双图切换效果
2019/07/09 Javascript
微信小程序自定义头部导航栏(组件化)
2019/11/15 Javascript
JS实现transform实现扇子效果
2020/01/17 Javascript
python调用摄像头显示图像的实例
2018/08/03 Python
Python字符串中删除特定字符的方法
2020/01/15 Python
浅谈多卡服务器下隐藏部分 GPU 和 TensorFlow 的显存使用设置
2020/06/30 Python
css3 线性渐变和径向渐变示例附图
2014/04/08 HTML / CSS
使用CSS3来实现滚动视差效果的教程
2015/08/24 HTML / CSS
HTML5 source标签:媒介元素定义媒介资源
2018/01/29 HTML / CSS
西班牙美妆电商:Perfume’s Club(有中文站)
2018/08/08 全球购物
Linden Leaves官网:新西兰纯净护肤品
2020/12/20 全球购物
公务员职务工作的自我评价
2013/11/01 职场文书
大学活动邀请函
2014/01/28 职场文书
《落花生》教学反思
2014/02/25 职场文书
领导班子个人对照检查材料(群众路线)
2014/09/26 职场文书
2014法院四风问题对照检查材料思想汇报
2014/10/04 职场文书
简单租房协议书(范本)
2014/10/13 职场文书
工作检讨书500字
2014/10/19 职场文书
行政撤诉申请书
2015/05/18 职场文书
爱鸟护鸟的宣传语
2015/07/13 职场文书