能够写出可维护的面向对象JavaScript代码不仅可以节约金钱Q还能让你很受欢q。不信?有可能你自己或者其他什么h有一天会回来重用?的代码。如果能量让这个经历不那么痛苦Q就可以节省不少旉。地球h都知道,旉是金钱。同LQ你也会因ؓ帮某人省M头疼的过E而获得他的偏爱?但是Q在开始探索如何编写可l护的面向对象JavaScript代码之前Q我们先来快速看看什么是面向对象。如果已l了解面向对象的概念了,可以直接蟩 q下一节?/p>
什么是面向对象Q?/strong>
面向对象~程主要通过代码代表现实世界中的实质?象。要创徏对象Q首先需要写一?#8220;c?#8221;来定义? cd乎可以代表所有的东西Q̎P员工Q导航菜单,汽RQ植物,q告Q饮料,{等。而每ơ要创徏对象的时候,׃cd例化一个对象。换句话_是创徏c?的实例做为对象。事实上Q通常处理一个以上的同类事物时就会用到对象。另外,只需要简单的函数式程序就可以做的很好。对象实质上是数据的容器。因此在一 个employee对象中,你可能要储存员工P姓名Q入职日期,职称Q工资,资历Q等{。对象也包括处理数据的函敎ͼ也叫?#8220;Ҏ”Q。方法被用作媒介 来确保数据的完整性,以及在储存之前对数据q行转换。例如,Ҏ可以接收L格式的日期然后在储存之前其转化成标准化格式。最后,c还可以l承其他?cR承可以让你在不同cM重复使用相同代码。例如,银行账户和音像店账户都可以承一个基本的账户c,里面包括个h信息Q开h期,分部信息Q等{。然 后每个都可以定义自己的交易或者借款处理{数据结构和Ҏ?/p>
警告QJavaScript面向对象是不一L
在上一节中Q概qCl典的面向对象编E的基本知识。说l典是因为JavaScriptq不遵@q些规则。相反地QJavaScript的类是写成函数的样子Q而承则是通过原型实现的。原型承基本上意味着使用原型属性来实现对象的承,而不是从cȝ承类?/p>
———————————————–
?012-4-25 11Q?1Q?5 更新】:Ҏ微博|友@高翌?的反馈,前文中有?#8220;JS 面向对象”的内容不够细。现推荐《Javascript 面向对象~程》《再谈javascript面向对象~程》两?a target="_self">文章?/p>
———————————————–
对象的实例化
以下是JavaScript中对象实例化的例子:
// 定义Employeec?div number2="" index1="" alt1=""> function Employee(num, fname, lname) { this .getFullName = function () { return fname + " " + lname; } }; // 实例化Employee对象 var john = new Employee( "4815162342" , "John" , "Doe" ); alert( "The employee's full name is " + john.getFullName()); |
在这里,有三个重炚w要注意:
1?#8220;class”函数名的W一个字母要大写。这表明该函数的目的是被实例化而不是像一般函C栯调用?/p>
2、在实例化的时候用了new操作W。如果省略掉new而仅仅调用函数则会生很多问题?/p>
3、因为getFullName指定lthis操作W了Q所以是公共可用的,但是fname和lname则不是。由Employee函数产生的闭包给了getFullName到fname和lname的入口,但同时对于其他类仍然是私有的?/p>
原型l承
下面是JavaScript中原型承的例子Q?/p>
// 定义Humanc?div number2="" index1="" alt1="">function Human() { this .setName = function (fname, lname) { this .fname = fname; this .lname = lname; } this .getFullName = function () { return this .fname + " " + this .lname; } } // 定义Employeec?/code> function Employee(num) { this .getNum = function () { return num; } }; //让Employeel承Humanc?/code> Employee.prototype = new Human(); // 实例化Employee对象 var john = new Employee( "4815162342" ); john.setName( "John" , "Doe" ); alert(john.getFullName() + "'s employee number is " + john.getNum()); |
q一ơ,创徏的Humancd含hcȝ一切共有属?#8212;—我也fname和lname放进MQ因Z仅仅是员工才有名字,所有h都有名字。然后将Human对象赋值给它的prototype属性?/p>
通过l承实现代码重用
在前面的例子中,原来的Employeec被分解成两个部分。所有的人类通用属性被Ud了HumancMQ然后让Employeel承 Human。这L话,Human里面的属性就可以被其他的对象使用Q例如StudentQ学生)QClientQ顾客)QCitizenQ公 民)QVisitorQ游客)Q等{。现在你可能注意CQ这是分割和重用代码很好的方式。处理Human对象Ӟ只需要承Human来用已存在的属 性,而不需要对每种不同的对象都重新一一创徏。除此以外,如果要添加一?#8220;中间名字”的属性,只需要加一ơ,那些l承?Human cȝ可以立马用了。反而言之,如果我们只是惌l一个对象加“中间名字”的属性,我们q接加在那个对象里面,而不需要在Human c里面加?/p>
1、PublicQ公有的Q和PrivateQ私有的Q?/strong>
接下来的主题Q我惌谈类中的公有和私有变量。根据对象中处理数据的方式不同,数据会被处理为私有的或者公有的。私有属性ƈ不一定意味着其他人无法访问。可能只是某个方法需要用到?/p>
● 只读
有时Q你只是惌在创建对象的时候能有一个倹{一旦创建,׃惌其他人再改变q个倹{ؓ了做到这点,可以创徏一个私有变量,在实例化的时候给它赋倹{?/p>
function Animal(type) { var data = []; data[ 'type' ] = type; this .getType = function () { return data[ 'type' ]; } } var fluffy = new Animal( 'dog' ); fluffy.getType(); // q回 'dog' |
在这个例子中QAnimalcM创徏了一个本地数ldata。当 Animal对象被实例化Ӟ传递了一个type的值ƈ该值放|在data数组中。因为它是私有的Q所以该值无法被覆盖QAnimal函数定义了它的范 _。一旦对象被实例化了Q读取type值的唯一方式是调用getTypeҎ。因为getType是在Animal中定义的Q因此凭借Animal产生 的闭包,getType可以q到data中。这L话,虽可以读到对象的cd却无法改变?/p>
有一炚w帔R要,是当对象被l承Ӟ“只读”技术就无法q用。在执行l承后,每个实例化的对象都会׃n那些只读变量q覆盖其倹{最单的解决办法是将cM的只d量{换成公共变量。但是你必须保持它们是私有的Q你可以使用Philippe在评Z提到的技术?/p>
● PublicQ公有)
当然也有些时候你惌Ld某个属性的倹{要实现q一点,需要用this操作W?/p>
function Animal() { this .mood = '' ; } var fluffy = new Animal(); fluffy.mood = 'happy' ; fluffy.mood; // q回 'happy |
q次Animalcd开了一个叫mood的属性,可以被随意读写。同样地Q你q可以将函数指定l公有的属性,例如之前例子中的getType函数。只是要注意不要lgetType赋|不然的话你会毁了它的?/p>
完全U有
最后,可能你发C需要一个完全私有化的本地变量。这L话,你可以用与W一个例子中一L模式而不需要创建公有方法?/p>
function
Animal() {
var
secret =
"You'll never know!"
}
var
fluffy =
new
Animal();
2、写灉|的API
既然我们已经谈到cȝ创徏Qؓ了保持与产品需求变化同步,我们需要保持代码不q时。如果你已经做过某些目或者是长期l护q某个品,那么你就 应该知道需求是变化的。这是一个不争的事实。如果你不是q么想的话,那么你的代码在还没有写之前就注定荒废。可能你H然需要将选项卡中的内容弄成动?形式Q或是需要通过Ajax调用来获取数据。尽准预未来是不大可能Q但是却完全可以代码写灉|以备来不时之需?/p>
● Saner参数列表
在设计参数列表的时候可以让代码有前L。参数列表是让别人实C代码的主要接触点Q如果没有设计好的话Q是会很有问题的。你应该避免下面q样的参数列表:
function Person(employeeId, fname, lname, tel, fax, email, email2, dob) { }; |
q个cd分脆弱。如果在你发布代码后惌d一个中间名参数Q因为顺序问题,你不得不在列表的最后往上加。这让工作变得尴。如果你没有为每个参数赋值的话,会十分困难。例如:
var ara = new Person(1234, "Ara", "Pehlivanian", "514-555-1234", null, null, null, "1976-05-17"); |
操作参数列表更整z也更灵zȝ方式是用这个模式:
function Person(employeeId, data) { }; |
有第一个参数因是必需的。剩下的在对象的里面Q这h可以灉|q用?/p>
|
q个模式的漂亮之处在于它x侉Kd高度灉|。注意到fax, email和email2完全被忽略了。不仅如此,对象是没有特定顺序的Q因此哪里方便就在哪里添加一个中间名参数是非常容易的Q?/p>
var ara = new Person( 1234 , { fname: "Ara" , mname: "Chris" , lname: "Pehlivanian" , tel: "514-555-1234" , dob: "1976-05-17" }); |
c里面的代码不重要,因ؓ里面的值可以通过索引来访问:
function Person(employeeId, data) { this.fname = data['fname']; }; |
如果data['fname'] q回一个|那么他就被设定好了。否则的话,没被讑֮好,也没有什么损失?/p>
随着旉逝,产品需求可能对你类的行为有更多的要求。而该行ؓ却与你类的核心功能没有半毛钱关系。也有可能是cȝ唯一一U实玎ͼ好比在一个?卡的面板获取另一个选项卡的外部数据Ӟ这个选项卡面板中的内容变灰。你可能xq些功能攑֜cȝ里面Q但是它们不属于那里。选项卡条的责d于管?选项卡。动d获取数据是完全不同的两码事,也必M选项卡条的代码分开。唯一一个让你的选项卡条不过时而又那些额外的功能排除在外的方法是Q允许将?为嵌入到代码当中。换句话_通过创徏事gQ让它们在你的代码中与关键时L钩,例如onTabChange, afterTabChange, onShowPanel, afterShowPanel{等。那L话,他们可以LC你的onShowPanel事g挂钩Q写一个将面板内容变灰的处理器Q这样就皆大Ƣ喜了?JavaScript库让你可以够容易地做到q一点,但是你自己写也不那么难。下面是使用YUI 3的一个例子?/p>
<script type= "text/javascript" src= "http://yui.yahooapis.com/combo?3.2.0/build/yui/yui-min.js" ></script> <script type= "text/javascript" > YUI(). use ( 'event' , function (Y) { function TabStrip() { this .showPanel = function () { this .fire( 'onShowPanel' ); // 展现面板的代? this .fire( 'afterShowPanel' ); }; }; // 让TabStrip有能力激发常用事? Y.augment(TabStrip, Y.EventTarget); var ts = new TabStrip(); // lTabStrip的这个实例创建常用时间处理器 ts.on( 'onShowPanel' , function () { //在展C面板之前要做的? }); ts.on( 'onShowPanel' , function () { //在展C面板之前要做的其他? }); ts.on( 'afterShowPanel' , function () { //在展C面板之后要做的? }); ts.showPanel(); }); |
q个例子有一个简单的 TabStrip c,其中有个showPanelҎ。这个方法激发两个事ӞonShowPanel和afterShowPanel。这个能力是通过?Y.EventTarget扩大cL实现的。一旦做成,我们实例化了一个TabStrip对象Qƈ一堆处理器都分配给它。这是用来处理实例的唯一行ؓ 而又能避免乱当前类的常用代码?/p>
ȝ
如果你打重用代码,无论是在同一|页Q同一|站q是跨项目操作,考虑一下在c里面将其打包和l织h。面向对象JavaScript很自然地 帮助实现更好的代码组l以及代码重用。除此以外,有点q见的你可以保代码h_的灵zL,可以在你写完代码后持l用很长时间。编写可重用的不q时 JavaScript代码可以节省你,你的团队q有你公司的旉和金钱。这l对能让你大受欢q?/p>
HTML5 火吗Q看?oschina 三天两头?xx ?xxx q道了。本文ؓ你推荐最新的 10 ?HTML5 相关的教E,或许能启发你目中的思\?/p>
Canvas ?HTML5 里非帔R要的一部分Q特别是在游戏开发中必不可少?br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />
此教E中介绍如何使用 Three.js q个 js 三位模型库?br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />
讲述如何使用 HTML5 创徏 Web 相册Q基?nbsp;jQuery ?nbsp;Quicksand 插g?br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />
如果你想创徏自己的交互式bannerQ那阅读这文章吧
HTML5 ?Web Audio API 入门
创徏一个移动版的贪吃蛇Q?HTML5 Canvas ?JavaScript 技?br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />
创徏非规则的囑փ
使用 HTML5 Canvas 创徏一个画囄?br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />
展示 HTML5 ?Sliverlight 5 技?br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />
开发一个简单的 HTML5 Canvas 游戏