内容要点:

一.JS中的类

1.JAVA或其他类似强类型 面向对象语言的 类成员的模样

实例字段:它们是基于实例的属性或变量,用以保存独立对象的状态。

实例方法: 它们是类的所有实例所共享的方法,由每个独立的实例调用

类字段:这些属性或变量是属于类的,而不是属于类的某个实例的。

类方法:这些方法是属于类的,而不是属于类的某个实例的

2.JS中的类牵扯三种不同的对象,三种对象的属性的行为和下面三种类成员非常相似:

构造函数对象:

之前提到,构造函数(对象)为JS的类定义了名字。任何添加到这个构造函数对象中的属性都是类字符和类方法(如果属性值是函数的话就是类方法)。

原型对象:

原型对象的属性被类的所有实例所继承,如果原型对象的属性值是函数的话,这个函数就作为 类的实例的方法 来调用

实例对象:

类的每个实例都是一个独立的对象,直接给这个实例定义的属性是不会为所有实例对象所共享的。定义在实例上的非函数属性,实际上是实例的字段。

3.JS中定义类的步骤可以缩减为一个分三步算法。

第一步,先定义一个构造函数,并设置初始化新对象的实例属性。

第二步,给构造函数的prototype对象定义实例的方法。

第三步,给构造函数定义类字段和类属性。

我们可以将这三个步骤封装进一个简单的defineClass()函数中(这里用到了例6-2中的extend()函数和例8-3中的改进版)

//一个用以定义简单类的函数

function defineClass(constructor,  //用以设置实例的属性的函数

methods, //实例的方法,复制至原型中

static)   //类属性,复制至构造函数中

{

if (methods) extend( constructor,prototype,methods );

if (statics) extend( constructor,statics );

return constructor;

}

//这是Range类的另一个实现

var SimpleRange = defineClass(function(f,t){ this.f=f;this.t=t; },

{

includes:function(x){ return this.f <=x && x<=this.t;}

toString:function(){ return this.f + "..." +this.t; }

},

{

upto:function(t){ return new SimpleRange(o,t); }});

二.例9-3 Complex.js : 表示复数的类

/*Complex.js : 这个文件定义了Complex类,用来描述复数。回忆一下,复数是实数和虚数的和,并且虚数i是-1的平方根*/

/*这个构造函数为它所创建的每个实例定义了实例字段r和i,这两个字段分别保存复数的实部和虚部,它们是对象的状态*/

function Complex(real,imaginary){

if(isNaN(real) || isNaN(imaginary)) throw new TypeError();   //确保两个实参都是数字,如果不都是数字则抛出错误

this.r = real; //复数的实部

this.i = imaginary; //复数的虚部

}

/*类的实例方法 定义为原型对象的函数值属性,这里定义的方法可以被所有实例继承,并为它们提供共享的行为。需要注意的是,JS类额实例方法必须使用关键字this来存取实例的字段。*/

//当前复数对象加上另一个对象,并返回一个新的计算和值后的复数对象

Complex.prototype.add = function(that){ return new Complex(this.r + that.r , this.i + that.i); };

//当前复数乘以另一个复数,并返回一个新的计算乘积之后的复数对象

Complex.prototype.mul = function(that){ return new Complex(this.r * that.r - this.i*that.i , this.r*that.i + this.i*that.r); };

//计算复数的模,复数的模定义为原点(0 , 0)到复平面的距离

Complex.prototype.mag = function(){ return new Complex(this.r * this.r + this.i * this.i); };

//复数的求负运算

Complex.prototype.neg = function(){ return new Complex(-this.r , -this.i); };

//将复数对象转换为一个字符串

Complex.prototype.toString = function(){ return "{" +this.r + "," +this.i + "}"; };

//检测当前复数对象是否和另外一个复数值相等

Complex.prototype.equals = function(that){ return that !=null &&          //必须有定义且不能是null

that.constructor === Complex &&     //并且必须是Complex的实例,

this.r === that.r && this.i === that.i; //并且必须包含相同的值

};

/*类字段(比如常量)和类方法 直接定义为构造函数的属性。需要注意的是,类的方法通常不使用关键字this,它们只对其参数进行操作*/

//这里预定义了一些对复数运算有帮助的类字段,它们的命名全都是大写,用以表明它们是常量(在ES5中,还能设置这些类字段的属性为只读)

Complex.ZERO = new Complex(0,0);

Complex.ONE = new Complex(1,0);

Complex.I = new Complex(0,1);

//这个类方法将由实例对象的toString方法返回的字符串格式解析为一个Complex对象,或者抛出一个类型错误异常

Complex.parse = function(s){

try{     //假设解析成功

var m = Complex._format.exec(s); //利用正则表达式进行匹配

return new Complex(parseFloat(m[1]),parseFloat(m[2]));

}catch(x){      //如果解析失败则抛出异常

throw new TypeError("Can't parse ' " + s + " ' as a complex number.");

}

};

//定义类的"私有字段",这个字段在Complex.parse()中用到了下划线前缀表明它是类内部使用的,而不属于类的公有API的部分

Complex._format = /^\{(^,]+),([^}]+)\}$/;

代码分析:

从例9-3中所定义的Complex类可以看出,我们用到了构造函数、实例字段、实例方法、类字段和类方法,看一下这段实例代码:

var c = new Complex(2,3); //使用构造函数创建新的对象

var d = new Complex(c.i , c.r); //用到了c的实例属性

c.add(d).toString(); //=>"{5,5}":使用了实例的方法

//这个稍微复杂的表达式用到了类方法和类字段

Complex.parse(c.toString()).         //将c转换为字符串

add(c.neg()).          //加上它的负数

equals(Complex.ZERO)  //结果应当永远是“零”

《JS权威指南学习总结--9.3 JS中JAVA式的类继承》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. idea导入web项目的部署

    前几天 参考 http://zyjustin9.iteye.com/blog/2172712 这篇文章的部署,一直没有问题,今天又部署了一个项目,按照这个步骤,死活却不能部署成功.最后发现,原来是在部 ...

  2. ACM第二题 生理周期

    人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维敏捷,精力容易 ...

  3. mysql添加mcafee 审计插件

    插件源码地址https://github.com/mcafee/mysql-audit插件安装方法https://github.com/mcafee/mysql-audit/wiki/Installa ...

  4. angular1 实现页面切换及tag页面

    tag页面实现<div class="b_gray" style="padding-left:24px;border-bottom:1px solid #ccc&q ...

  5. Kafka发送消息失败原因

    Kafka发送消息方法如下: Properties properties = new Properties(); properties.put("zookeeper.connect" ...

  6. 【Time系列五】个性时钟与秒表升级版

    从昨天到现在,一直在研究这个看起来超级简单的时钟.界面非常简洁大方. 虽然是简单,可是这个对齐的问题还是把我整得一塌糊涂.谁叫作者不解释清楚的. 参考:http://bbs.fishc.com/thr ...

  7. PHP基础语法思维导图

  8. db2 备份还原

    一.导入导出 ixf: db2 export to /tmp/xxx.csv of ixf lobs to . xml to . modified by codepage=1208 "sel ...

  9. 《Intel汇编第5版》 汇编调用子过程

    一.Call和Ret指令 二.在子过程中需要自己保存可能会修改掉的寄存器值,这里可以使用USES伪指令来生成 三.一个数组求和的汇编例子 TITLE Call a Proc Demo INCLUDE ...

  10. Action3D

    抖动效果-Shaky3D 波浪效果-Waves3D 翻转效果-FlipX3D 凸镜效果-Ripple3D 液体效果-Liquid 扭动效果-Twirl 破碎效果-ShatteredTiles3D 瓷砖 ...