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 相关文章推荐
jquery $.ajax入门应用一
Nov 19 Javascript
一个XML格式数据转换为图表的例子
Feb 09 Javascript
表单序列化与jq中的serialize使用示例
Feb 21 Javascript
基于jquery和svg实现超炫酷的动画特效
Dec 09 Javascript
Javascript基础_嵌入图像的简单实现
Jun 14 Javascript
jsp 自动编译机制详细介绍
Dec 01 Javascript
jQuery EasyUI Layout实现tabs标签的实例
Sep 26 jQuery
微信小程序返回箭头跳转到指定页面实例解析
Oct 08 Javascript
vue-devtools的安装和使用步骤详解
Oct 17 Javascript
VUE实现强制渲染,强制更新
Oct 29 Javascript
JavaScript canvas基于数组生成柱状图代码实例
Mar 06 Javascript
Vue + iView实现Excel上传功能的完整代码
Jun 22 Vue.js
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
JS与PHP向函数传递可变参数的区别实例代码
2011/05/18 PHP
PHP图片处理之图片旋转和图片翻转实例
2014/11/19 PHP
PHP开发的微信现金红包功能示例
2017/06/29 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
2019/08/12 PHP
nodejs教程 安装express及配置app.js文件的详细步骤
2013/05/11 NodeJs
鼠标拖动实现DIV排序示例代码
2013/10/14 Javascript
返回上一页并自动刷新的JavaScript代码
2014/02/19 Javascript
JavaScript实现关键字高亮功能
2014/11/12 Javascript
js实现上一页下一页的效果【附代码】
2016/03/10 Javascript
谈一谈js中的执行环境及作用域
2016/03/30 Javascript
JavaScript生成带有缩进的表格代码
2016/06/15 Javascript
ionic组件ion-tabs选项卡切换效果实例
2016/08/27 Javascript
jQuery通过改变input的type属性实现密码显示隐藏切换功能
2017/02/08 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
2017/02/20 Javascript
基于JavaScript实现幸运抽奖页面
2020/07/05 Javascript
浅谈Postman解决token传参的问题
2018/03/31 Javascript
mpvue跳转页面及注意事项
2018/08/03 Javascript
总结javascript三元运算符知识点
2018/09/28 Javascript
详解vue 不同环境配置不同的打包命令
2019/04/07 Javascript
Vue form表单动态添加组件实战案例
2019/09/02 Javascript
JS 事件机制完整示例分析
2020/01/15 Javascript
JS实现canvas简单小画板功能
2020/06/23 Javascript
Vue3 响应式侦听与计算的实现
2020/11/11 Javascript
使用python根据端口号关闭进程的方法
2018/11/06 Python
python实现美团订单推送到测试环境,提供便利操作示例
2019/08/09 Python
TensorFlow学习之分布式的TensorFlow运行环境
2020/02/05 Python
在pycharm中实现删除bookmark
2020/02/14 Python
借助HTML5 Canvas来绘制三角形和矩形等多边形的方法
2016/03/14 HTML / CSS
实例讲解使用SVG制作loading加载动画的方法
2016/04/05 HTML / CSS
DKNY品牌官网:纽约大都会时尚风格
2016/10/20 全球购物
酒店保洁主管岗位职责
2013/11/28 职场文书
2014年办公室人员工作总结
2014/12/09 职场文书
html5中sharedWorker实现多页面通信的示例代码
2021/05/07 Javascript
Python机器学习算法之决策树算法的实现与优缺点
2021/05/13 Python
python 标准库原理与用法详解之os.path篇
2021/10/24 Python
win10滚动条自动往上跑怎么办?win10滚动条自动往上跑的解决方法
2022/08/05 数码科技