[读书笔记]JavaScript面向对象编程-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

[读书笔记]JavaScript面向对象编程

简介:
摘要:

      我们在开发Web程序时或多或少都会应用到Javascript脚本程序,在当今的AJAX如此盛行的时代,JS的作用将不断的提升。这个新一代的 Web 应用程序的复杂性和交互性需要程序员以完全不同的方法来编写JavaScript 代码,我们在编写一次性的脚本显然已经不能够满足这样的需求。面向对象编程 (OOP) 是一种流行的编程方法,很多 JavaScript 库中都使用这种方法,以便更好地管理和维护基本代码。我们可以从ASP.NET AJAX库或SilverLight库以及经常见到的prototype.js库等等都采用了这种编程方式。JS支持OOP,但是又和C++,C#等非常不一样,所以这种概念一直会让人难以琢磨,这编文章将讲述 JavaScript 语言实际上如何支持面向对象编程,我们又如何应用这种方式来编写我们JS程序。
 

JavaScript对象

      在.NET中我们知道,万物皆为对象,也就是类实例化后得到的就是对象,每个对象都有各自不同的属性和方法。JavaScript中的对象和他有所不同,我们知道在JS中我们可以通过.[]运算符来获取或设置对象中的方法或属性,我们可以把它想象为包含键/值对的字典。下面我们来看个例子:
1None.gifvar obj = new Object();
2None.gifobj.Now= new Date();
3None.gifalert(obj.Now); 

     我们可以用[]运算符来达到同样的效果:
1None.gifvar obj=new Object();//{};
2None.gifobj["Now"]=new Date();
3None.gifalert(obj.Now);

     我们还可以直接定义它的属性,效果一样:
1ExpandedBlockStart.gifvar obj={"Now"new Date()};
2None.gifalert(obj.Now);

    以上三种方法都能够达到同样得效果,如果你用过C#3.0他的匿名赋值就有点像,也许它就是跟JS学的(只是猜测)。您不必预先声明属性Now — 如果 obj 没有该名称的属性,该属性将被直接添加到 obj。这是不是很像字典,我们可以不断地往字典里加入键/值对,我想把它想象成字典最容易理解多了。

JavaScript函数

     在上面所讲述的是对象的属性,我们可以把属性值直接付给一个键(名称),其实JS的方法也是这样。JavaScript 函数实际上是具有与它关联的可执行代码的对象,我们定义方法时可以把我们的函数符给一个对象(类)中的名称(方法名称)。对于方法我想大家应该都很熟悉,这里就不多说了。

JavaScript原型

     在使用 JavaScript 的面向对象编程中,原型对象是个核心概念。在 JavaScript 中对象是作为现有示例(即原型)对象的副本而创建的,该名称就来自于这一概念。此原型对象的任何属性和方法都将显示为从原型的构造函数创建的对象的属性和方法。可以说,这些对象从其原型继承了属性和方法。

      在 JavaScript 中,每个函数都有名为“prototype”的属性,用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身。 当我们用用new创建对象时,所创建的对象将继承此函数的prototype属性。

       每个 JavaScript 对象都继承一个原型链,而所有原型都终止于 Object.prototype。当您尝试访问对象的属性/方法时,JavaScript 将检查该属性/方法是否是在该对象中定义的。如果不是,则检查对象的原型。如果还不是,则检查该对象的原型的原型,如此继续,一直检查到 Object.prototype。所以我想如果用很长的prototype链对于性能方面应该会有所影响,但是现在的客户端足以承受,因此在ASP.NET AJAX中用了相当大的prototype。

JavaScript闭包

       由于我对这个概念也不是特别的熟悉这个咚咚,它是JavaScript的一个高级功能,闭包是当内部函数绑定到它的外部函数的本地变量时所发生的运行时现象,这很容易让我们想到在C#中匿名的方法。我们可以通过一下实例来更好的理解这个功能:
1None.gifvar isMoreThan300 = filter(
2ExpandedBlockStart.gif    function(x) return (x > 300? true : false; }
3None.gif    num);
4None.gif

       以上事例说明了当前数num是否比300大,如果比300大我们就返回true,否则反回false。但我们可能还需要判断是否比400,500,200...等时,我们可以通过下列方法来完成:
 1ExpandedBlockStart.giffunction makeMoreThan(lowerBound) {
 2ExpandedSubBlockStart.gif    return function(numberToCheck) {
 3InBlock.gif        return (numberToCheck > lowerBound) ? true : 
 4InBlock.gif
 5InBlock.giffalse;
 6ExpandedSubBlockEnd.gif    }
;
 7ExpandedBlockEnd.gif}

 8None.gif
 9ExpandedBlockStart.giffunction filter(pred, numberToCheck) {
10InBlock.gif    return pred(numberToCheck);
11ExpandedBlockEnd.gif}

12None.gif
13None.gif
14None.gifvar isMoreThan10 = makeMoreThan(10);
15None.gifvar isMoreThan100 = makeMoreThan(100);
16None.gifalert(filter(isMoreThan10,1));
17None.gifalert(filter(isMoreThan100,111));

      上面的代码运行后返回的结果是:false;true。从上面的代码可以看出makeMoreThan这个方法返回的是匿名函数,而这个匿名函数接受一个参数numberToCheck。根据作用域规则,当函数makeMoreThan退出时,变量lowerBound将失效,然而返回的匿名方法仍然带着lowerBound甚至在makeMoreThan结束后很长的一段时间内仍是如此。这样我们就可以利用这个特性来模拟.NET等中的私有变量,代码如下:
1ExpandedBlockStart.giffunction Person(name) {
2ExpandedSubBlockStart.gif    this.getName = function() return name; };
3ExpandedSubBlockStart.gif    this.setName = function(newName) { name = newName; };
4InBlock.gif    var gender;         
5ExpandedSubBlockStart.gif    this.getGender = function() return gender; };
6ExpandedSubBlockStart.gif    this.setGender  = function(newGender) { gender = newGender; };

       然后我们就可以调用Person中的方法给变量赋值,而其中的name和gender则就是我们的私有变量,当然这和.NET中所说的私有变量肯定是不同的。

Javascript继承

       在OOP中继承是不可少的,在C#中要继承某个类只要用:运算符就可继承,但是在Javascript中可没有那么简单,我们还需要写点代码才能够达到此效果。通过下面的例子就能够很好的说明:
 
 1ExpandedBlockStart.giffunction Person(name){
 2ExpandedSubBlockStart.gif   this.getName = function(){return name;};
 3ExpandedSubBlockStart.gif   this.setName = function(newName){name = newName;};
 4ExpandedBlockEnd.gif}

 5None.gif
 6ExpandedBlockStart.gifPerson.prototype.toString = function(){
 7InBlock.gif   return "My name is:" + this.getName();
 8ExpandedBlockEnd.gif}

 9None.gif
10ExpandedBlockStart.giffunction XiaMenPerson(name,address){
11InBlock.gif   Person.call(this,address);
12ExpandedSubBlockStart.gif   this.getAddress = function(){return address;};
13ExpandedBlockEnd.gif}

14None.gif
15None.gifXiaMenPerson.prototype = new Person();//继承prototype链
16None.gif
17None.gifXiaMenPerson.prototype.constructor = XiaMenPerson;//指定当前构造函数
18None.gif//重写toString()方法,调用基类中的getName属性。
19ExpandedBlockStart.gifXiaMenPerson.prototype.toString = function(){
20InBlock.gif   return "My name is:"+this.getName()+"\nCome from:"+this.getAddress();
21ExpandedBlockEnd.gif}
;
22None.gif
23None.gifvar p = new Person("网魂小兵");
24None.gifalert(p);
25None.gif//My name is:网魂小兵
26None.gifvar xp = new XiaMenPerson("网魂小兵","厦门");
27None.gifalert(xp);
28None.gif//My name is:网魂小兵
29None.gif//Come from:厦门
30None.gifalert(xp instanceof XiaMenPerson);//true;
31None.gifalert(xp instanceof Person);//true;
32None.gifalert(xp instanceof Object);//true;

    本文转自网魂小兵博客园博客,原文链接:http://www.cnblogs.com/xdotnet/archive/2007/05/20/js_oop_program.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: