这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
其实,面向对象的思想是独立于编程语言的,例如在 C# 中,在一个静态类的静态方法中,按照过程式开发调用一系列静态函数,我们很难说这是面向对象的编程,相反,象 jquery 和 extjs 这样优秀的 javascript 库,却处处体现着面向对象的设计思想。本文不打算探讨 javascript 是否能够算做面向对象的编程语言,这个问题是重视中国式考试的人应该关注的,我这里只是简单的说明如何在 javascript 中使用面向对象的编程思想。 面向对象首先要有对象。在 javascript 中创建一个对象非常简单:
对于正在从事或者打算从事编程的人来说,面向对象是一个耳熟能详的词,几乎每一个人都能列举出一些面向对象的编程语言,例如 C++,JAVA,C# 等等。
- var o={};
这样就产生了一个对象,我们可以很方便的给这个对象添加属性和方法:
- o.name="object name";
- o.showName=function(){
- alert(o.name);
- }
不过大多数人还是习惯把对象的属性和方法放在定义对象的一对 {} 里边:
- var o = {
- name: "object name",
- showName: function() {
- alert(o.name);
- }
- }
访问属性和方法有两种方式,第一种:
- alert(o.name);
- o.showName();
这种写法很常见,C# 中调用对象的属性和方法也是这种方式。还有一种是 javascript 中比较特别的,使用属性或者方法的名字作为索引来进行访问:
- alert(o["name"]);
- o["showName"]();
这好像有点和孔乙己 "茴香的茴字有几种写法" 差不多了,事实上,很少有人使用索引来调用对象的属性或者方法。 除了我们自定义的属性和方法,我们的对象还有一个 constructor 属性以及 toString() 等方法。这些属性和方法是从 Object 内置对象来的,所有的对象都会有这些属性和方法。其中 constructor 属性指向构造出该对象的构造函数。我们没有使用构造函数来创建对象,事实上,js 的解释器会使用 Object 构造函数。如果我们自己定义了构造函数,那么便可以通过该构造函数来创建对象,这样可以使得创建的对象具有相同的属性和方法,这便开始有点面向对象的味道了。好,我们从一个简单的例子开始看看如何创建一个构造函数吧:
- function Person(name, sex, age) {
- this.name = name;
- this.sex = sex;
- this.age = age;
- this.showInfo = function() {
- alert("姓名:" + this.name + " 性别:" + this.sex + " 年龄:" + this.age);
- }
- }
我们定义了一个名字叫 Person 的构造函数,该构造函数有三个属性和一个方法,通过构造函数来产生一个对象并调用方法也非常简单:
- var zhangsan = new Person("张三", "男", 18);
- zhangsan.showInfo();
运行后我们可以看到弹出一个对话框,显示出这个叫张三的人的信息:
我们还可以看看对象的 constructor 属性来看看 zhangsan 的构造函数是不是我们定义好的 Person:
- alert(zhangsan.constructor);
结果如图:
可以看到,正是我们的 Person 构造函数。 不过,这里还是有点问题,每一次我们构造一个对象,都会在内存中为属性和方法分配内存空间,而事实上,所有的对象完全可以用同一个方法,并不需要有多个方法的副本,这样有些浪费内存空间。既然意识到了这个问题,让我们来想想如何解决吧。一个很自然的想法是,既然我们只想为方法分配一次内存空间,那么我们可以设置一个值用来标识方法的内存空间是否已经分配,按照这个思路,我们将构造函数做如下修改:
- function Person(name, sex, age) {
- this.name = name;
- this.sex = sex;
- this.age = age;
- if (typeof Person._initialized == "undefined") {
- this.showInfo = function() {
- alert("姓名:" + this.name + " 性别:" + this.sex + " 年龄:" + this.age);
- }
- Person._initialized = true;
- }
- }
这里,我们用一个成员_initialized 来指示是否已经对方法进行了内存空间的分配。当第一个对象构造的时候_initialized 未被定义,所以我们的判断语句为真,这时会对方法进行了定义并分配内存空间,然后把_initialized 的值设置为 true,用以表明方法的内存空间已经分配了。第二个对象构造的时候则不会再进入判断,因而也不会再一次分配内存空间。似乎没什么问题,运行一下看看,张三的信息依然正常显示。虽然不辛苦,不过解决了一个小问题,还是庆祝下吧,来盘回锅肉,我要大快朵颐。还没开吃,一个叫李四的 MM 也想让电脑弹出她的个人信息。OK,很简单,再构造一个对象,然后调用 showInfo 方法就可以了:
- var lisi = new Person("李四", "女", 28);
- lisi.showInfo();
为了照顾 MM,还把这段放在了张三的前边。MM 的信息正确显示出来了,可是张三的资料不见了。这下张三不乐意了,排名放在 MM 后边也罢了,但好歹得有名字啊。这可苦了我这编程人员,回锅肉看来没办法吃了,先改 bug 吧。打开 firebug,看到 MM 的信息显示之后出现错误,提示为:zhangsan.showInfo is not a function。设置断点看看,构造 zhangsi 对象以后发现并没有 showInfo 这个方法。原来 showInfo 方法虽然只有一个,但是存在于第一个对象之中,第二个对象并不能访问。那么,究竟如何才能让同一个构造函数产生的对象共用同一个函数呢?javascript 中的 prototype 给我们提供了这个功能。根据 javascript 的规范中描述,每一个构造函数都有一个 prototype 属性用于实现继承和属性的共享。我们的 showInfo 方法也可以看作是一个属性,该属性指向一个函数的引用。现在我们使用 prototype 来使得我们的方法可以共享,代码的改动很简单,把 this.showInfo 改成 Person.prototype.showInfo 就可以了,改动之后的代码如下:
- function Person(name, sex, age) {
- this.name = name;
- this.sex = sex;
- this.age = age;
- if (typeof Person._initialized == "undefined") {
- Person.prototype.showInfo = function() {
- alert("姓名:" + this.name + " 性别:" + this.sex + " 年龄:" + this.age);
- }
- Person._initialized = true;
- }
- }
使用该构造函数生成两个对象:
- var lisi = new Person("李四", "女", 28);
- lisi.showInfo();
- var zhangsan = new Person("张三", "男", 18);
- zhangsan.showInfo();
运行之后先显示李四的信息,然后是张三的信息。现在两个人都满意了,可惜我的回锅肉已经凉了
来源: http://www.phperz.com/article/17/0416/286201.html