《HTML5 Canvas游戏开发实战》——1.6 JavaScript中的面向对象

1.6 JavaScript中的面向对象

在本章开始的时候就已经说了,对于游戏开发来说,使用面向对象的方法进行编程是很有必要的。所以在介绍游戏开发之前,先来了解一下如何使用JavaScript进行面向对象的编程。可以说,JavaScript是一种基于对象的语言,但是,它又不是一种真正的面向对象的编程语言,因为它的语法中不存在class(类)。本节将分析和解决如何在JavaScript中实现封装和继承等面向对象的问题。
1.6.1 类
JavaScript对象很抽象,所以下面将以实际的例子来解释如何定义一个简单的类。以下是一个没有任何属性和方法的类的定义:
function MyClass(){};
你可能会想,这不就是个简单函数的声明吗?没错,这个函数就是一个类的定义的实现。如何使用这个类呢?看下面的代码:

var cls1 = new MyClass();

这样,利用new就可以生成MyClass的一个实例了。所以,在JavaScript中,可以说函数就是类,类就是函数。
我们知道,一个实例的封装包含属性和方法的封装。那么如何实现呢?接着看下面的代码:

function MyClass(name,age){
    this.name = name;
    this.age = age;
};
var cls1 = new MyClass("lufy",10);
alert(cls1.name + ":" + cls1.age);//[lufy:10]

从上面的代码可以看出,在函数内使用this就能给函数本身增加属性值。而在上面的代码中就给MyClass函数增加了name和age两个属性。
同样,还可以利用this给这个类增加一个toString方法,代码如下:

function MyClass(name,age){
    this.name = name;
    this.age = age;
    this.toString() = function(){
        alert(this.name + ":" + this.age);
    };
};
var cls1 = new MyClass("lufy",10);
cls1.toString();//[lufy:10]

经过测试可以发现,我们已经成功地给MyClass增加了toString方法。另外,也可以用以下代码来添加方法:

function MyClass(name,age){
    this.name = name;
    this.age = age;
};
var cls1 = new MyClass("lufy",10);
cls1.toString() = function(){
    alert(this.name + ":" + this.age);
};
cls1.toString();//[lufy:10]

虽然这样也能给这个类添加一个方法,但需要注意的是,这种方式只是给cls1这个实例增加了方法,并未给MyClass本身增加方法。比如,下面的代码会出错:

function MyClass(name,age){
    this.name = name;
    this.age = age;
};
var cls1 = new MyClass("lufy",10);
cls1.toString() = function(){
    alert(this.name + ":" + this.age);
};
cls1.toString();//[lufy:10]
var cls2 = new MyClass("legend",12);
cls2.toString();//报错

出错的原因是cls2内并不存在toString方法。可见想要通过这种方式来给一个类的本身增加方法是行不通的。要想给MyClass类的本身增加方法,需要将方法定义在MyClass这个函数的内部,这样的话,每声明一个新的实例,就会将MyClass本身复制一遍。但是,如果MyClass类里包含十几个或几十个方法,那么每次都得把这些方法复制一遍,这显然不是最优的做法。
既然不能将一个类(函数)所包含的方法都定义在函数的内部,那么,如何来给一个类添加方法呢?这就需要用到函数的prototype属性了。每一个函数都会包含一个prototype属性,这个属性指向了一个prototype对象,我们可以指定函数对应的prototype对象。如果不指定,则函数的prototype属性将指向一个默认的prototype对象,并且此默认prototype对象的constructor属性又会指向该函数。
当用构造函数创建一个新的对象时,新的对象会获取构造函数的prototype属性所指向的prototype对象的所有属性和方法,这样一来,构造函数对应的prototype对象所做的任何操作都会反映到它所生成的对象上,所有的这些对象将共享与构造函数对应的prototype对象的属性和方法。
虽然新创建的对象可以使用它的构造函数所指向的prototype对象的属性和方法,但不能像构造函数那样直接调用prototype对象(对象没有prototype属性)。
简而言之,就是如果我们使用函数的prototype对象来给函数添加方法,那么在创建一个新的对象的时候,并不会复制这个函数的所有方法,而是指向了这个函数的所有方法。
具体的实现方法参看下面的代码:

function MyClass(name,age){
    this.name = name;
    this.age = age;
};
MyClass.prototype.toString = function(){
    alert(this.name + ":" + this.age);
}
var cls1 = new MyClass("lufy",10);
cls1.toString();//[lufy:10]
var cls2 = new MyClass("legend",12);
cls2.toString();//[legend:12]

对于prototype对象来说,由于存在的是指向的关系,所以避免了不必要的浪费,如图1-10所示。

如果要加入多个方法,也可以使用下面的方式:

function MyClass(name,age){
    this.name = name;
    this.age = age;
};
MyClass.prototype = {
    toString:function(){
        alert(this.name + ":" + this.age);
    },
    sayHellow:function(){
        alert(this.name + ",你好!");
    }
};

var cls1 = new MyClass("lufy",10);
cls1.toString();//[lufy:10]
cls1.sayHellow ();//[lufy,你好!]

这就是JavaScript中给类添加方法的实现,它是利用prototype来实现封装的。
1.6.2 静态类
那么,JavaScript中的静态类又是如何实现的呢?其实下面的函数本身就可以当作静态类来用:

var StaticClass = function(){};
StaticClass.name = "StaticName";
StaticClass.Sum = function(value1,value2){
return value1 + value2;
};
alert(StaticClass.name);//[StaticName]
alert(StaticClass.Sum(1,3));//[4]

这样,在使用静态类的时候,就无须创建新的实例了,可直接用“类名+点+属性或方法”的方式。
1.6.3 继承
上面只讲了类的封装,那么如何实现类的继承呢?如有如下两个构造函数:

function PeopleClass(){
    this.type = "人";
};
PeopleClass.prototype = {
    getType:function(){
        alert("这是一个人");
    }
};
function StudentClass(name,sex){
    this.name = name;
    this.sex = sex;
};

如何让“学生”对象来继承“人”对象呢?可使用apply方法将父对象的构造函数绑定在子对象上,代码如下:

function PeopleClass(){
    this.type = "人";
};
PeopleClass.prototype = {
    getType:function(){
        alert("这是一个人");
    }
};
function StudentClass(name,sex){
    PeopleClass.apply(this, arguments);
    this.name = name;
    this.sex = sex;
};
var stu = new StudentClass("lufy","男");
alert(stu.type);//[人]

从运行结果来看,StudentClass继承了PeopleClass的属性“人”。
而方法的继承,只要循环使用父对象的prototype进行复制,即可达到继承的目的。具体方法如下:

function PeopleClass(){
    this.type = "人";
};
PeopleClass.prototype = {
    getType:function(){
        alert("这是一个人");
    }
};
function StudentClass(name,sex){
    PeopleClass.apply(this, arguments);
    var prop;
    for(prop in PeopleClass.prototype){
        var proto = this.constructor.prototype;
        if(!proto[prop]){
            proto[prop] = PeopleClass.prototype[prop];
        }
        proto[prop]["super"] = PeopleClass.prototype;
    }
    this.name = name;
    this.sex = sex;
};
var stu = new StudentClass("lufy","男");
alert(stu.type);//[人]
stu.getType();//[这是一个人]

以上,就是JavaScript中继承的实现。了解了这些知识后,就可以在JavaScript中使用面向对象的方法了,这对于提高开发效率是很有帮助的。

时间: 2024-10-22 22:23:30

《HTML5 Canvas游戏开发实战》——1.6 JavaScript中的面向对象的相关文章

《HTML5 Canvas游戏开发实战》——导读

前言 为什么要写这本书 并非计算机专业的我,却最终走上了编程之路,并写了这样一本书,为什么呢?其实一切都是因为和游戏结了缘. 小时候我非常喜欢玩游戏,为了玩游戏和小伙伴们干过不少调皮捣蛋的事情.初中为了得到自己的第一台游戏机,和父亲打赌,破天荒拿了全班第一名.当然有了游戏机的相伴,从那以后就再也没有拿过第一名了.因为数学上较有优势,所以读大学时选择的是数学专业,没有选读计算机让后来做开发的我多少感到有些遗憾.和其他人一样,大学是真正改变我人生的时期,第一次有了电脑,第一次从室友嘴里得知QQ为何物

《HTML5 Canvas游戏开发实战》——2.4 图片操作

2.4 图片操作 无论我们开发的是应用程序还是游戏软件,都是离不开图片,没有图片就无法让整个页面漂亮起来.开发游戏的时候,游戏中的地图.背景.人物.物品等都是由图片组成的,所以图片的显示和操作非常重要.Canvas中提供了drawImage函数和putImageData函数来绘制图片,在本节中将一一讲解.2.4.1 利用drawImage绘制图片 drawImage函数有3种函数原型,其语法如下: drawImage(image, dx, dy); drawImage(image, dx, dy

《HTML5 Canvas游戏开发实战》——第1章 准备工作

第一部分 准备工作篇 第1章 准备工作 作为本书的第一章,我们先来学习一下什么是HTML5.什么是Canvas元素.HTML5的开发与运行环境,以及如何选择它的开发工具等基础知识.对于游戏开发来说,如果不以面向对象为基础,那么开发思路就会不够清晰,代码也难以做到工整,可读性差,会给后期维护带来很大困难.所以在进入游戏开发之前,本章还会对JavaScript的面向对象编程进行简要的讲解.

《HTML5 Canvas游戏开发实战》——第3章 Canvas高级功能

第3章 Canvas高级功能 在进行游戏开发的时候,离不开图形的变化,比如放大.缩小.旋转.平移等功能都是游戏开发中常用的变形手段.同时,为了使得游戏画面更加丰富多彩,还需要设置界面的颜色来实现更加精美的画面.本章将通过介绍Canvas的变形.色彩调整等高级功能来实现这些奇妙的变化.

《HTML5 Canvas游戏开发实战》——2.1 绘制基本图形

2.1 绘制基本图形 所谓基本图形,就是指线.矩形.圆等最简单的图形,任何复杂的图形都是由这些简单的图形组合而成的.我们首先来了解一下这些简单图形的绘制方法.2.1.1 画线你可能是第一次接触Canvas绘图.首先,我们通过绘制一个简单的直线来学习Canvas的功能.其代码如代码清单2-1所示.代码清单 2-1 <!DOCTYPE HTML> <html> <body> <canvas id="myCanvas" width="200

《HTML5 Canvas游戏开发实战》——第2章 Canvas基本功能

第2章 Canvas基本功能 本章主要讲解HTML5 Canvas的基本功能,利用Canvas的API,展示一些基本图形的绘制及操作方法,包括画线.画图.文字操作及图片操作等.

《HTML5 Canvas游戏开发实战》——1.7 小结

1.7 小结 本章主要带大家认识一下HTML5,了解一下HTML5的背景,并且做了一些准备工作,包括开发环境的搭建和JavaScript面向对象知识的介绍.下一章我们将进入正题,从HTML5的Canvas标签的基础属性开始,一步步地学习如何开发各种类型的游戏.

《HTML5 Canvas游戏开发实战》——3.4 小结

3.4 小结 本章主要首先介绍了Canvas中的缩放.平移.旋转和倾斜等基本变形功能的实现,并且利用这些基本变形的组合操作实现了图片的扭曲:接着介绍了色彩的渲染:最后运用之前所介绍的内容制作了一个简单的自定义画板.到此Canvas的绘图相关API就基本上介绍完了.只要运用好这些API,就可以制作出更多更复杂的效果.但是直接运用这些API来开发游戏是相当不方便的,一些很简单的功能可能都需要大量的代码来实现,比如本章的图片扭曲功能,必须根据图片扭曲后的顶点坐标去计算相应的参数,而制作游戏时可能会有更

《HTML5 Canvas游戏开发实战》——3.2 图形的渲染

3.2 图形的渲染 Canvas提供了很多对颜色进行操作的API,可实现渐变.反色等效果.这一节中将举例说明如何实现这些效果.3.2.1 绘制颜色渐变效果的图形 颜色的渐变分为线性渐变和径向渐变,下面分别进行说明. 1 . 线性渐变 使用createLinearGradient函数和addColorStop函数可以实现线性渐变功能. createLinearGradient函数的原型如下: createLinearGradient(x1,y1,x2,y2) 其中的4个参数分别是渐变的出发点坐标(