JavaScript中的类(Class)详细介绍


Posted in Javascript onDecember 30, 2014

在JavaScript中,可以使用类(Class)来实现面向对象编程(Object Oriented Programming)。不过,JavaScript中的类与Java中的有所不同,其相应的定义和使用也不一样。

JavaScript中类的定义

在JavaScript中,所有从同一个原型对象(prototype)处衍生出来的对象组成了一个类;也就是说,JavaScript中的类是一个对象集合的概念,如果两个对象它们的prototype相同,那么它们就属于同一个类;JavaScript中的类甚至都不需要类名。以下面的代码为例:

var p = {x:42};

var a = Object.create(p);

var b = Object.create(p);

console.log(a === b);//false

console.log(Object.getPrototypeOf(a) === Object.getPrototypeOf(b));//true

在上述例子中,对象a和b拥有相同的原型对象(prototype) p,因此a和b属于同一个类(虽然这个类都没有类名),它们从原型对象p处继承了值为42的属性x。

从这个例子中可以看到,原型对象的作用就相当于模板,可以由之衍生/创建出多个对象,其地位与Java语言中的类代码(Class code)相同,是JavaScript中类定义的核心。以下这个例子中的原型对象就呈现出更像类代码的样子:

var p = {

 INCREMENT_BY : 1,

 increment : function(x){

  return x + this.INCREMENT_BY;

 }

}

var a = Object.create(p);

var b = Object.create(p);

console.log(a.increment(7));//8

console.log(b.increment(9));//10

上述例子中,原型对象p定义了一个值为1的property (INCREMENT_BY)和一个名为increment的函数;对象a和b从p这个模板处获取了INCREMENT_BY和increment函数。当调用对象a或b的increment函数时,JavaScript会试图获取a或b的INCREMENT_BY值(this.INCREMENT_BY);由于INCREMENT_BY是从p中获取的,因此其值都是1 — 从模板中获取的,值都相同的变量,类似于Java中的静态类变量(static variable),因此上面的例子中对INCREMENT_BY变量命名时使用了全大写字符。

在上面的例子中,所有从模板p处创建出来的对象(属于同一个类的这些对象),其属性和行为都是一模一样的。但实际上对于同一个类的不同对象,它们除了拥有类所定义的属性/行为以外,往往具有一些自身所特有的属性与行为。因此,如果需要将prototype这个模板当作类来使用的话,就必须对每一个从中衍生出来的对象进行一定的定制:

var p = {

 INCREMENT_BY : 1,

 increment : function(x){

  return x + this.INCREMENT_BY + this.custom_increment_by;

 }

}

var a = Object.create(p);

var b = Object.create(p);

a.custom_increment_by = 0;

b.custom_increment_by = 1;

console.log(a.increment(7));//8

console.log(b.increment(9));//11

在这个例子中,从模板p处创建出来的对象a和b拥有一个彼此间值不一定相等的变量custom_increment_by,而它们的increment()函数这个行为的最终结果则与custom_increment_by的值相关。一般来说,对新建对象进行定制化的工作往往放在统一的函数中进行:

var p = {

 INCREMENT_BY : 1,

 increment : function(x){

  return x + this.INCREMENT_BY + this.custom_increment_by;

 }

}

function getIncrementalClassObject(customIncrementByValue){

 var incrementalObj = Object.create(p);

 incrementalObj.custom_increment_by = customIncrementByValue;

 return incrementalObj;

}

var a = getIncrementalClassObject(0);

var b = getIncrementalClassObject(1);

console.log(a.increment(7));//8

console.log(b.increment(9));//11

如此,便通过原型对象p和getIncrementalClassObject()函数完成了一个类的定义:可以通过调用getIncrementalClassObject()函数来获取原型对象都是p的对象,而在调用getIncrementalClassObject()函数过程中可以对这些新建对象进行一定的定制化。值得注意的是,此时这个已经定义了的类还没有类名,为了方便描述,姑且称之为Incremental。

回顾getIncrementalClassObject()函数中所做的工作,可以看到从Incremental这个类中创建新的对象所经历的过程如下:

1.创建一个空对象,并将其原型对象定义为p。
2.根据不同的参数值,对这个新建的空对象进行定制。
3.返回已经定制完成的新对象。

在JavaScript中,可以通过使用Constructor(构造函数)来快速地完成类的定义以及新对象的创建。

JavaScript中的Constructor(构造函数)

从上述Incremental类这个例子中可以看到,定义新的类需要两部分代码:创建原型对象作为模板、创建自定义函数对新对象进行初始化;而从类中创建新的对象则经历了三个过程:指定新对象的原型对象、定制/初始化新对象、返回这个新对象。在JavaScript中,这一切都可以通过Constructor(构造函数)来完成。

JavaScript中的Constructor是一个函数(function),承担对新对象进行初始化的职责;而这个Constructor函数的prototype则作为模板用于创建新对象。仍以上述Incremental类为例,用Constructor来重写代码后是这样的:

function Incremental(customIncrementByValue){

  this.custom_increment_by = customIncrementByValue;

}

Incremental.prototype = {

  INCREMENT_BY : 1,

 increment : function(x){

  return x + this.INCREMENT_BY + this.custom_increment_by;

 }

}
var a = new Incremental(0);

var b = new Incremental(1);

console.log(a.increment(7));//8

console.log(b.increment(9));//11

通过new关键词,使用Constructor函数来创建新对象这一过程,其实际上经历了以下几个阶段:

创建一个新的空对象。

1.将这个对象的原型对象指向constructor函数的prototype属性。
2.将这个对象作为this参数,执行constructor函数。
3.这与之前的getIncrementalClassObject()函数中所做的工作是一样的。

类名

在使用Constructor创建对象时,相应的对象也就有了“类名”,这可以从instanceof操作符的结果上得到验证:

console.log(a instanceof Incremental);//true

console.log(b instanceof Incremental);//true

不过,instanceof操作符并不判断对象是否由Incremental这一构造函数所创建,instanceof操作符只判断对象的原型对象是否为Incremental.prototype。当存在两个prototype一样的构造函数时,instanceof操作符将统一返回true,而不会区分用于创建对象的构造函数到底是哪个。
function Incremental2(customIncrementByValue){

  this.custom_increment_by = customIncrementByValue + 3;

}

Incremental2.prototype = Incremental.prototype;

console.log(a instanceof Incremental2);//true
Javascript 相关文章推荐
百度留言本js 大家可以参考下
Oct 13 Javascript
Jquery异步请求数据实例代码
Dec 28 Javascript
JS实现拖动示例代码
Nov 01 Javascript
js调用浏览器打印模块实现点击按钮触发自定义函数
Mar 21 Javascript
jquery实现的随机多彩tag标签随机颜色和字号大小效果
Mar 27 Javascript
Javascript 函数parseInt()转换时出现bug问题
May 20 Javascript
js实现模拟银行卡账号输入显示效果
Nov 18 Javascript
jQuery绑定事件的四种方式介绍
Oct 31 Javascript
深入理解javascript函数参数与闭包
Dec 12 Javascript
jQuery弹出窗口打开链接的实现代码
Dec 24 Javascript
详解vue-router 2.0 常用基础知识点之router-link
May 10 Javascript
基于vue、react实现倒计时效果
Aug 26 Javascript
JavaScript实现防止网页被嵌入Frame框架的代码分享
Dec 29 #Javascript
jQuery实现ichat在线客服插件
Dec 29 #Javascript
jQuery中用dom操作替代正则表达式
Dec 29 #Javascript
jQuery中:animated选择器用法实例
Dec 29 #Javascript
纯JavaScript实现获取onclick、onchange等事件的值
Dec 29 #Javascript
JavaScript实现列出数组中最长的连续数
Dec 29 #Javascript
jQuery中document与window以及load与ready 区别详解
Dec 29 #Javascript
You might like
php中使用GD库做验证码
2016/03/31 PHP
PHP实现中国公民身份证号码有效性验证示例代码
2017/05/03 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
2017/08/15 PHP
Laravel实现搜索的时候分页并携带参数
2019/10/15 PHP
PHP程序员简单的开展服务治理架构操作详解(三)
2020/05/14 PHP
浅谈PHP之ThinkPHP框架使用详解
2020/07/21 PHP
js 多浏览器分别判断代码
2010/04/01 Javascript
JS中confirm,alert,prompt函数使用区别分析
2010/04/01 Javascript
js和php如何获取当前url的内容
2013/09/22 Javascript
Jquery 实现弹出层插件
2015/01/28 Javascript
浅析上传头像示例及其注意事项
2016/12/14 Javascript
JS使用正则实现去掉字符串左右空格的方法
2016/12/27 Javascript
详解bootstrap的modal-remote两种加载方式【强化】
2017/01/27 Javascript
详解nodejs微信公众号开发——4.自动回复各种消息
2017/04/11 NodeJs
前端构建工具之gulp的语法教程
2017/06/12 Javascript
angular内置provider之$compileProvider详解
2017/09/27 Javascript
利用three.js画一个3D立体的正方体示例代码
2017/11/19 Javascript
bootstrap中selectpicker下拉框使用方法实例
2018/03/22 Javascript
Vue项目全局配置微信分享思路详解
2018/05/04 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解
2019/01/19 Javascript
Vue-cli3生成的Vue项目加载Mxgraph方法示例
2020/05/31 Javascript
python实现12306抢票及自动邮件发送提醒付款功能
2018/03/08 Python
Python批处理更改文件名os.rename的方法
2018/10/26 Python
python自动化测试之如何解析excel文件
2019/06/27 Python
Python Django基础二之URL路由系统
2019/07/18 Python
centos7之Python3.74安装教程
2019/08/15 Python
Python基于Serializer实现字段验证及序列化
2020/11/04 Python
Python eval函数介绍及用法
2020/11/09 Python
购买原创艺术品:Zatista
2019/11/09 全球购物
考生诚信考试承诺书
2014/05/23 职场文书
本溪水洞导游词
2015/02/11 职场文书
免职通知
2015/04/23 职场文书
入党转正介绍人意见
2015/06/03 职场文书
电影雨中的树观后感
2015/06/15 职场文书
决心书格式范文
2015/09/23 职场文书