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实现无刷新DropDownList联动实现代码
Mar 08 Javascript
基于jquery封装的一个js分页
Nov 15 Javascript
jQuery左侧大图右侧小图焦点图幻灯切换代码分享
Aug 19 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
Dec 16 Javascript
js贪吃蛇游戏实现思路和源码
Apr 14 Javascript
jQuery遍历json的方法分析
Apr 16 Javascript
JS中对Cookie的操作详解
Aug 05 Javascript
详解jQuery lazyload 懒加载
Dec 19 Javascript
微信小程序request出现400的问题解决办法
May 23 Javascript
浅谈Angular文字折叠展开组件的原理分析
Nov 24 Javascript
小程序实现搜索界面 小程序实现推荐搜索列表效果
May 18 Javascript
通过实例了解Render Props回调地狱解决方案
Nov 04 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 number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
php实例分享之二维数组排序
2014/05/15 PHP
PHP中的gzcompress、gzdeflate、gzencode函数详解
2014/07/29 PHP
Laravel模板引擎Blade中section的一些标签的区别介绍
2015/02/10 PHP
php 浮点数比较方法详解
2017/05/05 PHP
tp5(thinkPHP5框架)时间查询操作实例分析
2019/05/29 PHP
jQuery 一个图片切换的插件
2011/10/09 Javascript
自定义jQuery选项卡插件实例
2013/03/27 Javascript
div当滚动到页面顶部的时候固定在顶部实例代码
2013/05/27 Javascript
JavaScript var声明变量背后的原理示例解析
2013/10/12 Javascript
根据表格中的某一列进行排序的javascript代码
2013/11/29 Javascript
使用JavaScript实现网页版Pongo设计思路及源代码分享
2014/06/16 Javascript
高性能JavaScript模板引擎实现原理详解
2015/02/05 Javascript
Jquery跨浏览器文本复制插件Zero Clipboard的使用方法
2016/02/28 Javascript
Extjs让combobox写起来简洁又漂亮
2017/01/05 Javascript
基于jQuery实现的单行公告活动轮播效果
2017/08/23 jQuery
JS计算输出100元钱买100只鸡问题的解决方法
2018/01/04 Javascript
JS实现调用本地摄像头功能示例
2018/05/18 Javascript
vue-cli中使用高德地图的方法示例
2019/03/28 Javascript
JavaScript Canvas编写炫彩的网页时钟
2019/10/16 Javascript
手把手教你实现 Promise的使用方法
2020/09/02 Javascript
深入了解Vue动态组件和异步组件
2021/01/26 Vue.js
[08:08]2014DOTA2国际邀请赛中国区预选赛精彩TOPPLAY
2014/06/25 DOTA
[40:57]TI4 循环赛第二日 iG vs EG
2014/07/11 DOTA
Python简单实现控制电脑的方法
2018/01/22 Python
python pandas中DataFrame类型数据操作函数的方法
2018/04/08 Python
PySide和PyQt加载ui文件的两种方法
2019/02/27 Python
从0开始的Python学习016异常
2019/04/08 Python
浅谈keras中loss与val_loss的关系
2020/06/22 Python
AmazeUI的下载配置与Helloworld的实现
2020/08/19 HTML / CSS
会计职业生涯规划书
2014/01/13 职场文书
2014年三八妇女节活动方案
2014/02/28 职场文书
干部作风建设工作总结
2014/10/29 职场文书
2019暑假学生安全口号
2019/06/27 职场文书
使用HTML+Css+transform实现3D导航栏的示例代码
2021/03/31 HTML / CSS
上手简单,功能强大的Python爬虫框架——feapder
2021/04/27 Python