在大多数面向对象语言中,对象老是由类中实例化而来,类和对象的关系就像模具跟模件同样。Javascript中没有类的概念,就算ES6中引入的class也不过是一种语法糖,本质上仍是利用原型实现。在原型编程语言中,类并非必需的,对象不必定须要由类实例化而来,而是经过克隆另一个对象来获得。java
原型模式是用来建立对象的一种模式。在以类为中心的语言中,要建立一个对象首先要指定这个对象的类型,而后实例化一个对象。使用原型模式建立对象时没必要关心对象的具体类型,而是找到一个对象,而后经过克隆来建立一个如出一辙的对象。因此在前者中若是要根据一个对象建立多个相同的对象,咱们须要先保存这个对象的全部属性信息,而后将属性信息设置到新建立的对象上,而在原型模式中咱们只须要使用克隆就能完成一样的功能。编程
在某些玄幻小说中常常会出现某些修真大能,以分身的形式游走世间。这个过程很适合原型模式的应用:浏览器
function Master(){app
this.blood = 100;编程语言
this.level = 6;ide
}函数
var noumenon = new Master();工具
noumenon.level = 9;学习
var ektype = Object.create(noumenon);this
console.log(ektype);
ES5提供了原生的克隆方法:Object.create,不支持这个方法的浏览器可使用以下代码:
function clone(obj)
function F(){};
F.prototype = obj;
return new F();
}
var ektype = clone(noumenon);
经过以上代码,咱们看到了如何经过原型模式来克隆出一个如出一辙的的对象。原型模式的真正意义并不是建立一个如出一辙的对象,而是提供一种建立对象的方式,Javascript的面向对象机制是基于原型模式的,他的对象系统就是使用原型模式,经过克隆来建立的,克隆是建立一个对象的过程和手段。以继承为例:
function Person(name){
this.name = name;
}
function Developer(lang){
this.language = lang;
}
var p = new Person('coder');
Developer.prototype = p;
var dev = new Developer('Javascript');
基于原型的继承体系,子类的每次实例化都是对其构造函数的prototype属性的克隆。因此每次建立Developer对象,其实都是在对p对象的克隆。
在Java等以类为中心的面向对象语言中,常用new实例化一个对象。可是Javascript是基于原型的面向对象语言,在这里new运算符建立对象的方式与Java中的new运算符并不相同,Javascript中的new运算符也是经过克隆来实例化对象的,克隆的是构造器函数的原型对象,new运算符的做用等同于以下代码:
function Person(name){
this.name = name;
}
function Developer(lang){
this.language = lang;
}
var p = new Person('coder');
Developer.prototype = p;
function _new(_Constructor) {
var that = Object.create(_Constructor.prototype);
var args = Array.prototype.slice.call(arguments, 1);
var other = _Constructor.apply(that, args);
return (typeof other === 'object' && other) ? other : that;
}
_new(Developer, 'JavaScript')
从这咱们也能够看出,Javascript的原型实际上存在着诸多矛盾,它的某些复杂语法看起来就像那些基于类的语言,这掩盖了它的原型机制。因此jQuery中尽可能避免使用new运算符来建立对象。
根据前面所说Javascript中新建立的对象都是基于原有对象的克隆,因此在Javascript中存在一个最原始的对象:Object.prototype,全部对象都是由它克隆而来。
这里所说的克隆是在Javascript原型模式这一大环境下的一种语义表达,在计算机的物理世界中并不存在真正的克隆。因此这里对于克隆应当理解为产生一个拥有__proto__属性指向原对象的对象的过程,原对象成为被克隆的对象,也就是构造函数的prototype对象。
拥有以上共识后,咱们能够获得在Javascript中原型编程的基本规则:
Javascript中绝大多数数据都是对象
要获得一个对象,不是经过实例化类,而是找到一个对象做为原型并克隆它
对象会记住它的原型
若是对象没法响应某个请求,他会把这个请求委托给它本身的原型
早先程序使用最简单的输入输出方式,用户在键盘输入数据,程序将信息输出在屏幕上。现代程序要求使用图形用户界面(Graphical User Interface,GUI),界面中有菜单、按钮等,用户经过鼠标选择菜单中的选项和点击按钮,命令程序功能模块。本章学习如何用Java语言编写GUI科学试验,如何经过GUI实现输入和输出。
AWT和Swing
先前用Java编写GUI程序,是使用抽象窗口工具包AWT(Abstract Window Toolkit).如今多用Swing。Swing能够看做是AWT的改良版,而不是代替AWT,是对AWT的提升和扩展。因此,在写GUI程序时,Swing和AWT都要做用。它们共存于Java基础类(Java Foundation Class,JFC)中。
尽管AWT和Swing都提供了构造图形界面元素的类,但它们的重要方面有所不一样:AWT依赖于主平台绘制用户界面组件;而Swing有本身的机制,在主平台提供的窗口中绘制和管理界面组件。Swing与AWT之间的最明显的区别是界面组件的外观,AWT在不一样平台上运行相同的程序,界面的外观和风格可能会有一些差别。然而,一个基于Swing的应用程序可能在任何平台上都会有相同的外观和风格。
Swing中的类是从AWT继承的,有些Swing类直接扩展AWT中对应的类。例如,JApplet、JDialog、JFrame和JWindow。
使用Swing设计图形界面,主要引入两个包:
javax.swing包:包含Swing的基本类;
java.awt.event包:包含与处理事件相关的接口和类。
因为Swing太丰富,不可能在一本教科书中给出Swing的全面介绍,但本章所介绍的有关Swing的知识,已足以让读者编写至关精美的GUI程序。
组件和容器
组件(component)是图形界面的基本元素,用户能够直接操做,例如按钮。容器(Container)是图形界面的的复合元素,容器能够包含组件,例如面板。
Java语言为每种组件都预约义类,程序经过它们或它们的子类各类组件对象,如,Swing中预约义的按钮类JButton是一种类,程序建立的JButton对象,或JButton子类的对象就是按钮。Java语言也为每种容器预约义类,程序经过它们或它们的子类建立各类容器对象。例如,Swing中预约义的窗口类JFrame是一种容器类,程序建立的JFrame或JFrame子类的对象就是窗口。
为了统一管理组件和容器,为全部组件类定义超类,把组件的共有操做都定义在Component类中。一样,为全部容器类定义超类Container类,把容器的共有操做都定义在Container类中。例如,Container类中定义了add()方法,大多数容器均可以用add()方法向容器添加组件。
Component、Container和Graphics类是AWT库中的关键类。为能层次地构造复杂的图形界面,容器被看成特殊的组件,能够把容器放入另外一个容器中。例如,把若干按钮和文本框分放在两个面板中,再把这两个面板和另外一些按钮放入窗口中。这种层次地构造界面的方法,能以增量的方式构造复杂的用户界面。
事件驱动程序设计基础
1.事件、监视器和监视器注册
图形界面上的事件是指在某个组件上发生用户操做。例如,用户单击了界面上的某个按钮,就说在这个按钮上发生了事件,这个按钮对象就是事件的击发者。对事件做监视的对象称为监视器,监视器提供响应事件的处理方法。为了让监视器与事件对象关联起来,须要对事件对象做监视器注册,告诉系统事件对象的监视器。
以程序响应按钮事件为例,程序要建立按钮对象,把它添加到界面中,要为按钮做监视器注册,程序要有响应按钮事件的方法。当“单击按钮”事件发生时,系统就调用已为这个按钮注册的事件处理方法,完成处理按钮事件的工做。
2.实现事件处理的途征
java语言编写事件处理程序主要有两种方案:一个是程序重设handleEvent(Eventevt),采用这个方案的程序工做量稍大一些;另外一个方案是程序实现一些系统设定的接口。java按事件类型提供多种接口,做为监视器对象的类须要实现相应的接口,即实现响应事件的方法。当事件发生时,系统内设的handleEvent(Event evt)方法就自动调用监视器的类实现的响应事件的方法。
java.awt.event包中用来检测并对事件作出反应的模型包括如下三个组成元素:
源对象:事件“发生”这个组件上,它与一组“侦听”该事件的对象保持着联系。
监视器对象:一个实现预约义的接口的类的一个对象,该对象的类要提供对发生的事件做处理的方法。
事件对象:它包含描述当事件发生时从源传递给监视器的特定事件的信息。
一个事件驱动程序要作的工做除建立源对象和监视器对象以外,还必须安排监视器了解源对象,或向源对象注册监视器。每一个源对象有一个已注册的监视器列表,提供一个方法能向该列表添加监视器对象。只有在源对象注册了监视器以后,系统才会将源对象上发生的事件通知监视器对象。
3.事件类型和监视器接口
在java语言中,为了便于系统管理事件,也为了便于程序做监视器注册,系统将事件分类,称为事件类型。系统为每一个事件类型提供一个接口。要做为监视器对象的类必须实现相应的接口,提供接口规定的响应事件的方法。
再以程序响应按钮事件为例,JButton类对象button能够是一个事件的激发者。当用户点击界面中与button对应的按钮时,button对象就会产生一个ActionEvent类型的事件。若是监视器对象是obj,对象obj的类是Obj,则类Obj必须实现AWT中的ActionListener接口,实现监视按钮事件的actionPerformed方法。button对象必须用addActionListener方法注册它的监视器obj。
程序运行时,当用户点击button对象对应的按钮时,系统就将一个ActionEvent对象从事件激发对象传递到监视器。ActionEvent对象包含的信息包括事件发生在哪个按钮,以及有关该事件的其余信息。
表 11-1 给出有必定表明性的事件类型和产生这些事件的部分Swing组件。实际事件发生时,一般会产生一系列的事件,例如,用户点击按钮,会产生ChangeEvent事件提示光标到了按钮上,接着又是一个ChangeEvent事件表示鼠标被按下,而后是ActionEvent事件表示鼠标已松开,但光标依旧在按钮上,最后是ChangeEvent事件,表示光标已离开按钮。可是应用程序一般只处理按下按钮的完整动做的单个ActionEvent事件。
表 11-1 组件和事件类型事件类型组件描述
ActionEventJButton,JCheckBox
JComboBox,JMenuItem
JRadioButton点击、选项或选择
ChangeEventJSlider调整一个可移动元素的位置
AdjustmentEventJScrollBar调整滑块位置
ItemEventJComboBox,JCheckBox
JRadioButton
JRadioButtonMenuItem
JCheckBoxMenuItem从一组可选方案中选择一个项
目
ListSelectionEventJList选项事件
KeyEvent
MouseEventJComponent 及其派生类操纵鼠标或键盘
CareEventJTextArea,JTextField选择和编辑文本
WindowEventWindow 及其派生类 JFrame对窗口打开、关闭和图标化
每一个事件类型都有一个相应的监视器接口,表11-2列出了每一个接口的方法。实现监视器接口的类必须实现全部定义在接口中的方法。
表 11-2 监视器接口方法监视器接口方法获取事件源的方法
ActionListeneractionPerformedgetSource,getActionCommand
ChangeListenerstateChangedgetSource
AdjustmentListeneradjustmentValueChangedgetAdjustable
FocusListenerfocusGained,
focusLost
ItemListeneritemStateChangedgetItemSelectable(),getSource()
ListSelectionListenervalueChangede.getSource().getSelectedValue()
KeyListenerkeyPressed,
keyReleased,
keyTyped
CareListenercareUpdate
MouseListenermouseClicked,
mouseEntered,
mouseExited,
mousePressed,
mouseReleased
MouseMontionListenermouseDragged,
mouseMoved
WindowListenerwindowClosed,
windowClosing,
windowDeactivated,
windowDeiconified,
windowIconified,
windowOpened