内容要点:

一.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. ng-class,与ng-click

    要求,后台传过来的数据,要求:(样式)性别为男的,变为灰色.(事件)并且没有点击事件,但女的有 <html> <head> <meta charset="utf ...

  2. eclipse集成配置JDK和Tomcat

    在eclipse中集成JDK和tomcat服务器方法很简单,我们可以在服务器上运行想要的东西.比如我们学习javaweb时就要用到. 工具/原料   eclipse,JDK,tomcat 方法/步骤 ...

  3. 学习笔记之html5相关内容

    写一下昨天学习的html5的相关内容,首先谈下初次接触html5的感受.以前总是听说html5是如何的强大,如何的将要改变世界.总是充满了神秘感.首先来谈一下我接触的第一个属性是  input的里面的 ...

  4. react-gulp-browserify

    环境搭配参照 http://www.cnblogs.com/guolaomao/p/6276877.html 前半部分的内容. 首先安装browserify npm install --save-de ...

  5. jquery插件autoComplete自动弹出

    导入 <link rel="stylesheet" href="${ctx }/static/plugins/jQuery-autoComplete-master/ ...

  6. equals和hashcode为什么要一起重写

    equals()方法与hashCode()的通用协定是:2.1 如果两个对象相等(equal),那么必须拥有相同的哈希码(hash code)2.2 即使两个对象有相同的哈希值(hash code), ...

  7. [MFC美化] Skin++使用详解-使用方法及注意事项

    主要分为以下几个方面: 1.Skin++使用方法 2.使用中注意事项 一. Skin++使用方法 SkinPPWTL.dll.SkinPPWTL.lib.SkinPPWTL.h ,将三个文件及相应皮肤 ...

  8. php核心编程

    搭建web服务器的环境(配置PHP的工作环境): 首先要配置php,在Apache的配置文件夹中httpd.conf中配置 1把php配置成Apache的一个功能模块 LoadModule php5_ ...

  9. 让IE的Button自适应文字宽度兼容

    width:auto; overflow:visible; 这样将可以去掉IE按钮文字两边多余的空格,并按照自己设置的padding 来显示

  10. 更改pip源

    ~/.pip/下新建pip.conf文件:(Windows下载Users/xxx/pip/pip.ini) [global] trusted-host = pypi.douban.com index- ...