内容要点:

一.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. [z] .net与java建立WebService再互相调用

    http://blog.csdn.net/yenange/article/details/5824967 : .net建立WebService,在Java中调用. 1.在vs中新建web 简单修改一下 ...

  2. [前端性能提升]--图片转化为base64

    图片的 base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址 意义:网页上的每一个图片,都是需要消耗一个 http 请求下载而来的(所有才有了 csssprites 技术 ...

  3. 第10章:DOM

  4. 一步步优化JVM六:优化吞吐量

    如果你已经进行完了前面的步骤了,那么你应该知道这是最后一步了.在这一步里面,你需要测试应用的吞吐量和为了更高的吞吐量而优化JVM.    这一步的输入就是应用的吞吐量性能要求.应用的吞吐量是在应用层面 ...

  5. Discuz! X3.2重置管理员账号

    主要是使用了Tools急诊箱.先看一下Tools急诊箱的主要功能: 多种模式在线安装Discuz!,或者重装 重置管理员账号:将把您指定的会员设置为管理员 关闭功能:一键关闭/打开 [站点|插件]的操 ...

  6. Makefile.am编写规则

    概念 Makefile.am是比Makefile更高层次的规则只需要指定要生成什么目标,依赖于什么文件,和要安装到什么目录.automake会根据Makefile.am来自动生成Makefile.in ...

  7. ecstore在MySQL5.7下维护报错WARNING:512 @ ALTER IGNORE TABLE

    ecstore在MySQL5.7下维护报错WARNING:512 @ ALTER IGNORE TABLE 打开 /app/base/lib/application/dbtable.php , 替换A ...

  8. 百度移动搜索自动转码太坑爹,JS跳转地址会被抓取

    这段时间碰到个很崩溃的问题,一个页面通过 script 加载请求服务端进行统计再输出js进行跳转,分为两个步骤分别统计, 打开页面通过script 请求远程服务器进行统计并输出要通过js使页面跳转的最 ...

  9. XTU 1243 2016

    $2016$长城信息杯中国大学生程序设计竞赛中南邀请赛$A$题 循环节. 循环节为$2016$,从数据范围以及题目中的一句话也能间接的体会出应该是有循环节的,并且循环节可能是$2016$. Feel ...

  10. [M]MagicTable转换异常解决方法

    ApplicationClass转换为_Application异常 这个问题可能是以前安装过不同版本的Office,没有完全卸载时导致的,可尝试通过以下方法解决: 1. 卸载Office,在 控制面板 ...