JavaScript面向对象编程入门教程_基础知识

尽管面向对象JavaScript与其他语言相比之下存在差异,并由此引发了一些争论,但毋庸置疑,JavaScript具有强大的面向对象编程能力

本文先从介绍面向对象编程开始,然后回顾JavaScript对象模型,最后演示JavaScript中的面向对象编程概念。

JavaScript回顾

如果你对诸如变量(variables)、类型(types)、函数(functions)、以及作用域(scope)等JavaScript概念觉得心里没底,那么你可以阅读重新介绍JavaScript中的这些主题。你还可以查阅JavaScript 1.5核心指南

面向对象编程

面向对象编程是一种编程范式(paradigm),即使用抽象来创建基于真实世界的模型。它使用了几种以前建立的范式技术,包括模块化(modularity)、多态(polymorphism)、和封装(encapsulation)。今天,许多流行的编程语言(比如Java、JavaScript、C#、C++、Python、PHP、Ruby、以及Objective-C)都支持面向对象编程(OOP)。

面向对象编程可视为使用协作对象集合来进行软件设计,这与传统观点相反,传统观点把程序视为函数集合,或者简化为计算机指令列表。在面向对象编程中,每个对象都具有以下能力:接收消息、处理数据、以及给其他对象发送消息。每个对象都可以视为一个独立的具有不同角色或责任的小机器。
面向对象编程旨在为编程提升更大的灵活性和可维护性,并在大规模软件工程中广泛流行。由于其非常重视模块化,因此面向对象代码旨在让开发更简单、稍后理解起来更容易,而且相对于较少采用模块化的编程方法,使得对于复杂情况及步骤的分析、编码和理解更加直接。

专用术语

类(Class)
~ 定义对象的特征(characteristics)。
对象(Object)
~ 类的实例(Instance)。
属性(Property)
~ 某一对象特征(characteristic),例如颜色。
方法(Method)
~ 某种对象能力,例如行走。
构造函数(Constructor)
~ 实例化(instantiation)时所调用的方法。
继承(Inheritance)
~ 一个类可以继承来自另一个类的特征。
封装(Encapsulation)
~ 一个类只定义该对象的特征,一个方法只定义该方法如何执行。
抽象(Abstraction)
~ 将某一对象的复杂继承、方法、属性结合在一起,而且必须能够模拟某一现实模型。
多态(Polymorphism)
~ 不同类可能会定义相同的方法或属性。
对于面向对象编程的进一步描述,参阅维基百科的面向对象编程词条。

基于原型的编程

基于原型的编程(Prototype-based programming)是一种面向对象编程风格,其中类(classes)并不存在,并且行为重用(在基于类的语言中称为继承)是通过粉饰充当原型的现存对象来完成的。这种模式也称为无类的(class-less)、面向原型的(prototype-oriented)、或基于实例(instance-based)的编程。
关于基于原型语言的最初(且非常规范的)示例就是由David Ungar和Randall Smith开发的Self编程语言。然而,这种无类编程风格最近越来越受欢迎,并且已被一些编程语言采用,例如avaScript、Cecil、NewtonScript、Io、MOO、REBOL、Kevo、Squeak(当使用Viewer框架来操纵Morphic组件时)、及其他几种语言。

JavaScript面向对象编程

核心对象(Core Objects)

JavaScript有几个包含在其核心中的对象;例如,Math、Object、Array、以及String等对象。下面的示例演示了如何使用Math对象的random()方法获取随机数。

复制代码 代码如下:

alert(Math.random());

提示:本例和所有其他示例都假设已在全局范围内定义了函数名alert(正如包含在web浏览器中的alert一样)。alert函数实际上不是JavaScript本身的一部分。

JavaScript核心对象列表,参阅JavaScript 1.5核心参考:全局对象(Global Objects)。

JavaScript中的每个对象都是一个Object对象的实例,并因此继承其所有属性和方法。

自定义对象(Custom Objects)

类(The Class)

JavaScript是基于原型的语言,其中不包含可在如 C++或Java中找到的类声明(class statement)。有时这会让一些习惯于具有类声明语言(languages with a class statement)的程序员感到困惑。不过,JavaScript用函数(functions)作为类。定义一个类简单到就是定义一个函数。在下例中,我们定义了名为Person(人)的新类。

复制代码 代码如下:

function Person() { }

对象(类实例)(The Object (Class Instance))

要创建obj对象的一个新实例,我们使用语句new obj,同时将结果(其类型是obj)赋给某个变量(variable),以便稍后访问。
在下例中,我们首先定义名为Person的类,然后创建两个实例(person1和person2)。

复制代码 代码如下:

function Person() {}
var person1 = new Person();
var person2 = new Person();

还可参阅新的实例化替代方法Object.create。

构造函数(The Constructor)

当实例化时(创建对象实例的瞬间)是会调用构造函数。构造函数是类的一个方法。而在JavaScript中,会函数(function)作为作为该对象的构造函数;因此,也就无需显式定义一个构造函数方法。类中声明的每个行为在实例化时都会执行。

构造函数用于设置对象属性或调用方法为使用该对象做准备。本文稍后会介绍,通过使用一种不同的语法来添加类方法及其定义 。

在下例中,当实例化Person时,Person类的构造函数会显示一个警告框。

复制代码 代码如下:

function Person() {
    alert('Person instantiated');
}
var person1 = new Person();
var person2 = new Person();

属性(对象属性)(The Property (object attribute))

属性是包含在类中的变量;每个对象实例都有这些属性。属性应设置在类(函数)的原型(prototype)属性中,以便继承正常工作。
在类中操作属性是通过this关键字实现的,this引用当前对象。在类外部访问(读或写)某个属性要通过以下语法:InstanceName.Property;这与C++、Java、以及其他一些语言所用语法相同。(在类内部使用this.Property的语法来获取或设置属性值)。

在下例中,我们为Person类定义gender(性别)属性,然后在初始化时定义该属性。

复制代码 代码如下:

function Person(gender) {
    this.gender = gender;
    alert('Person instantiated');
}
var person1 = new Person('Male'); // Male: 男
var person2 = new Person('Female'); // Female: 女
//显示person1的性别
alert('person1 is a ' + person1.gender); // person1 is a Male

方法(The methods)

方法遵循与属性相同的逻辑;区别在于它们是函数而且被定义为函数。调用方法与访问属性相似,不过你要在方法名末尾添加(),可能会有参数(arguments)。定义一个方法,就是为该类prototype属性上的某个命名属性指定一个函数;函数被分配到的那个名称就是在对象上调用该方法的名称。
在下例中,我们为Person类定义并使用sayHello()方法。

复制代码 代码如下:

function Person(gender) {
    this.gender = gender;
    alert('Person instantiated');
}
Person.prototype.sayHello = function() {
    alert('hello');
};
var person1 = new Person('Male');
var person2 = new Person('Female'); // 调用Person的sayHello方法。
person1.sayHello(); // hello

在JavaScript中,方法是作为属性被绑定到某个类/对象的普通函数对象,这意味着,可以“脱离上下文(out of the context)”来调用它们。考虑如下示例代码:

复制代码 代码如下:

function Person(gender) {
    this.gender = gender;
}
Person.prototype.sayGender = function() {
    alert(this.gender);
};
var person1 = new Person('Male');
var genderTeller = person1.sayGender;
person1.sayGender(); // alerts 'Male'
genderTeller(); // alerts undefined
alert(genderTeller === person1.sayGender); // alerts true
alert(genderTeller === Person.prototype.sayGender); // alerts true

此示例一次演示了多个概念。这表明,在JavaScript中没有“基于对象的方法(per-object methods)”,因为该方法的所有引用都指向完全相同的函数,即我们起初在原型上定义的那个函数。当某个函数被作为方法(或确切地说是属性)调用时,JavaScript会将当前的“对象上下文(object context)”“绑定”到特定的“this”变量。这与调用该函数对象的“call”方法等效,如下所示:

复制代码 代码如下:

genderTeller.call(person1); //alerts 'Male'e

更多相关信息,请参阅Function.call和Function.apply

继承(Inheritance)

继承是一种方法,用于创建作为一个或多个类专用版本的类。(JavaScript仅支持单类继承)。这个专用类通常被称为子类(child),而其他类通常被称为父类(parent)。在JavaScript中,你要完成继承,需将父类的实例赋给子类,然后将子类特化(specializing)。

提示:由于JavaScript不检测的子类的prototype.constructor(原型的构造函数),参阅Core JavaScript 1.5核心参考:Global Objects:Object:prototype属性,因此我们必须手动指定该值。

在下例中,我们定义Student类作为Person的子类。然后我们重新定义sayHello()方法,并添加sayGoodBye()方法。

复制代码 代码如下:

// 定义Person类
function Person() {}
Person.prototype.walk = function() {
    alert('I am walking!');
};
Person.prototype.sayHello = function() {
    alert('hello');
};
// 定义Student类
function Student() {
    //调用父类构造函数
    Person.call(this);
}
// 继承Person
Student.prototype = new Person(); // 修正构造函数指针,由于它指向Person
Student.prototype.constructor = Student; // 替换sayHello方法
Student.prototype.sayHello = function() {
    alert('hi, I am a student');
}
// 添加sayGoodBye方法
Student.prototype.sayGoodBye = function() {
    alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye(); // 检验继承
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true

封装

在上例中,Student无须知晓Person类的walk()方法是如何实现的,但仍可使用该方法;Student类无须显式定义该方法,除非我们想改变它。这称为封装(encapsulation),这样每个类继承其父类的方法,并且只需定义它所希望改变的东西。

抽象

抽象是一种机制(mechanism),允许对处理中的问题的当前部分进行建模。这可以通过继承(特化)或组合(composition)来实现。JavaScript通过继承实现特化(specialization),通过让类实例成为其他对象的属性值实现组合。
JavaScript的Function类继承自Object类(这说明模型的特化),并且Function.prototype属性是Object的实例(这说明了组合)。

复制代码 代码如下:

var foo = function() {};
alert('foo is a Function: ' + (foo instanceof Function));
alert('foo.prototype is an Object: ' + (foo.prototype instanceof Object));

多态

就像所有的方法和属性被定义在原型属性内部一样,不同的类可以定义具有相同名称的方法;方法的作用域限于定义它们的类之内。这仅当两个类之间没有父子关系(当一个类没有从继承链中的其他类继承时)时才为真。

提示

本文中所提出的面向对象编程实现技术不仅适用于JavaScript,因为就如何进行面向对象编程而言,这是非常灵活的。
同样,这里展示的技术既没有使用任何语言技巧(language hacks),也没有模仿其他语言的对象理论实现。
在JavaScript中,还有其他更高级的面向对象编程的技术,但是那些内容已超出了这篇介绍性文章的范围。

时间: 2024-10-17 11:42:13

JavaScript面向对象编程入门教程_基础知识的相关文章

理解JavaScript的变量的入门教程_基础知识

变量是用于存储信息的容器:   x=5; length=66.10; 还记得在学校里学过的代数吗? 当您回忆在学校学过的代数课程时,想到的很可能是:x=5, y=6, z=x+y 等等.   还记得吗,一个字母可以保存一个值(比如 5),并且可以使用上面的信息计算出 z 的值是 11.   您一定没有忘记,对吧.   这些字母称为变量,变量可用于保存值 (x=5) 或表达式 (z=x+y). JavaScript 变量 正如代数一样,JavaScript 变量用于保存值或表达式.   可以给变量

Javascript模块化编程详解_基础知识

模块化编程是一种非常常见Javascript编程模式.它一般来说可以使得代码更易于理解,但是有许多优秀的实践还没有广为人知. 基础 我们首先简单地概述一下,自从三年前Eric Miraglia(YUI的开发者)第一次发表博客描述模块化模式以来的一些模块化模式.如果你已经对于这些模块化模式非常熟悉了,大可以直接跳过本节,从"进阶模式"开始阅读. 匿名闭包 这是一种让一切变为可能的基本结构,同时它也是Javascript最棒的特性.我们将简单地创建一个匿名函数并立即执行它.所有的代码将跑在

用JavaScript实现对话框的教程_基础知识

 JavaScript支持三种重要类型的对话框.这些对话框可以用来引发和警报,或得到确认的任何输入或有来自用户的一种输入. 在这里,我们将一个一个地来看每个对话框:Alert 对话框: 一个警告对话框,主要是用来给一个警告信息给用户.就像如果一个输入字段要求输入一些文字,但用户不输入字段则作为验证,可以使用警告框,如下给出警告信息的一部分: <head> <script type="text/javascript"> <!-- alert("Wa

超级给力的JavaScript的React框架入门教程_基础知识

 React 是 Facebook 里一群牛 X 的码农折腾出的牛X的框架. 实现了一个虚拟 DOM,用 DOM 的方式将需要的组件秒加,用不着的秒删.React 扮演着 MVC 结构中 V 的角色, 不过你要是 Flux 搭配使用, 你就有一个很牛X的能让轻松让 M 和 V 同步的框架了,Flux 的事以后再说~组件们 在 React 中,你可以创建一个有特殊功能的组件,这在 HTML 元素里你是打着灯笼也找不到的,比如这个教程里的下拉导航.每个组件都有自己的地盘(scope),所以我们定义一

JavaScript的React框架中的JSX语法学习入门教程_基础知识

什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上这只是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码,当然你想直接使用纯Javascript代码写也是可以的,只是利用JSX,组件的结构和组件之间的关系看上去更加清晰. var MyComponent = React.createClass({/*...*/}); var myElement = <MyComponent som

使用AmplifyJS组件配合JavaScript进行编程的指南_基础知识

事件分发的作用 在为页面添加各类交互功能时,我们熟知的最简单的做法就是为页面元素绑定事件,然后在事件处理函数中,做我们想要做的动作.就像这样的代码: element.onclick = function(event){ // Do anything. }; 如果我们要做的动作不复杂,那么实际逻辑功能的代码,放在这里是可以的.如果今后需要修改,再到这段事件处理函数的位置来修改. 再进一步,为了做适当的代码复用,我们可能会把逻辑功能中的一部分分拆到一个函数内: element.onclick = f

JavaScript 中的事件教程_基础知识

事件是可以被JavaScript侦测到的行为. 事件 JavaScript使我们有能力创建动态页面.事件是可以被JavaScript侦测到的行为. 网页中的每个元素都可以产生某些可以触发JavaScript函数的事件.比方说,我们可以在用户点击某按钮时产生一个onClick事件来触发某个函数.事件在HTML页面中定义. 事件举例: 鼠标点击  页面或图像载入  鼠标悬浮于页面的某个热点之上  在表单中选取输入框  确认表单  键盘按键  注意:事件通常与函数配合使用,当事件发生时函数才会执行.

JavaScript方法和技巧大全_基础知识

这篇介绍JavaScript方面的日志,我在是Clang上看到的.作者介绍挺全面的,所以转载过来让感兴趣的朋友看一下.呵呵--- 有些时候你精通一门语言,但是会发现你其实整天在和其它语言打交道,也许你以为这些微不足道,不至于影响你的开发进度,但恰恰是这些你不重视的东西会浪费你很多时间,我一直以为我早在几年前就已经精通JavaScript了,直到目前,我才越来越觉得JavaScript远比我想象的复杂和强大,我开始崇拜它,就像崇拜所有OOP语言一样- 趁着节日的空隙,把有关JavaScript的方

Javascript &amp;amp; DHTML 实例编程(教程)基础知识_基础知识

[ 2007-04-11 14:31:50 | Author: never-online ] 这一节首先请下载JScript.chm这本手册,无论新手老手,有一本手册是免不了的,特别是对于新手,如果你没有空翻犀牛书,那么这本手册将是你了解这门语言的首选.下面所讲的大多数,手册上可以没有提及,或提及很少的内容. 以下的教程都是针对你对上面所说的JScript.chm这本手册了解的基础上而写的,如果你还没有看过JScript.chm,建议你先下载,边看手册,边看教程. JS的语法与大多数类C的语言差