《JS权威指南学习总结--9.3 JS中JAVA式的类继承》
内容要点:
一.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式的类继承》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- SQLite 约束
约束是在表的数据列上强制执行的规则.这些是用来限制可以插入到表中的数据类型.这确保了数据库中数据的准确性和可靠性. 约束可以是列级或表级.列级约束仅适用于列,表级约束被应用到整个表. 以下是在 SQL ...
- iOS 加载Image的两种方式
Apple官方文档对于加载image提供了两个方法 + (nullable UIImage *)imageNamed:(NSString *)name; + (nullable UIImage *)i ...
- 利用Hibernate监听器实现用户操作日志
网上搜索发现,实现用户操作日志的方式有:自定义注解方式.Hibernate拦截器方式.Hibernate监听器方式等. 1.自定义注解方式较为麻烦,需要进行操作记录的方法均需要添加注解,但是相对的操作 ...
- python爬虫框架scrapy初识(一)
Scrapy介绍 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中.所谓网络爬虫,就是一个在网上到处或定向抓取数据的 ...
- Theos 工程make package时报错
错误: /Applications/Xcode.app/Contents/Developer/usr/bin/make package requires you to have a layout/ d ...
- IOS 成员变量,全局变量,局部变量定义,static与extern的区别
IOS 成员变量,全局变量,局部变量定义,static与extern的区别 1,先说定义 1)成员变量定义:生存与该类的生命周期,变量存活周期跟你定义的该类实体对象一样:作用域是整个实体对象:可以在h ...
- linux下使用autoconf制作Makefile
第一步:常用工具安装:正所谓:"工欲善其事,必先利其器".我们常用的工具主要有GNU AutomakeGNU AutoconfGNU m4GNU Libtool1.查看自己系统中是 ...
- jsp中使用java函数
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> ${fn ...
- WPF Application
Application类作为启动的入口,在VS中,通常自动代码为我们继承了Application类,这样做的有点,我还没有理解到,但是我们先学到这个知识点. 为了能够更好的控制整个启动过程,包括得到A ...
- 制作自己的web字体
今天教给大家制作自己的web字体