盡管面向?qū)ο驤avaScript與其他語言相比之下存在差異,并由此引發(fā)了一些爭論,但毋庸置疑,JavaScript具有強大的面向?qū)ο缶幊棠芰?br> JavaScript回顧 如果你對諸如變量(variables)、類型(types)、函數(shù)(functions)、以及作用域(scope)等JavaScript概念覺得心里沒底,那么你可以閱讀重新介紹JavaScript中的這些主題。你還可以查閱JavaScript 1.5核心指南 面向?qū)ο缶幊淌且环N編程范式(paradigm),即使用抽象來創(chuàng)建基于真實世界的模型。它使用了幾種以前建立的范式技術,包括模塊化(modularity)、多態(tài)(polymorphism)、和封裝(encapsulation)。今天,許多流行的編程語言(比如Java、JavaScript、C#、C 、Python、PHP、Ruby、以及Objective-C)都支持面向?qū)ο缶幊蹋∣OP)。 專用術語 類(Class) 基于原型的編程 基于原型的編程(Prototype-based programming)是一種面向?qū)ο缶幊田L格,其中類(classes)并不存在,并且行為重用(在基于類的語言中稱為繼承)是通過粉飾充當原型的現(xiàn)存對象來完成的。這種模式也稱為無類的(class-less)、面向原型的(prototype-oriented)、或基于實例(instance-based)的編程。 JavaScript面向?qū)ο缶幊?/strong> 核心對象(Core Objects) JavaScript有幾個包含在其核心中的對象;例如,Math、Object、Array、以及String等對象。下面的示例演示了如何使用Math對象的random()方法獲取隨機數(shù)。 alert(Math.random()); 提示:本例和所有其他示例都假設已在全局范圍內(nèi)定義了函數(shù)名alert(正如包含在web瀏覽器中的alert一樣)。alert函數(shù)實際上不是JavaScript本身的一部分。 JavaScript核心對象列表,參閱JavaScript 1.5核心參考:全局對象(Global Objects)。 自定義對象(Custom Objects) 類(The Class) function Person() { } 對象(類實例)(The Object (Class Instance)) 要創(chuàng)建obj對象的一個新實例,我們使用語句new obj,同時將結(jié)果(其類型是obj)賦給某個變量(variable),以便稍后訪問。 在下例中,我們首先定義名為Person的類,然后創(chuàng)建兩個實例(person1和person2)。 function Person() {}
var person1 = new Person(); var person2 = new Person(); 還可參閱新的實例化替代方法Object.create。 當實例化時(創(chuàng)建對象實例的瞬間)是會調(diào)用構(gòu)造函數(shù)。構(gòu)造函數(shù)是類的一個方法。而在JavaScript中,會函數(shù)(function)作為作為該對象的構(gòu)造函數(shù);因此,也就無需顯式定義一個構(gòu)造函數(shù)方法。類中聲明的每個行為在實例化時都會執(zhí)行。 function Person() {
alert('Person instantiated'); } var person1 = new Person(); var person2 = new Person(); 屬性(對象屬性)(The Property (object attribute)) 屬性是包含在類中的變量;每個對象實例都有這些屬性。屬性應設置在類(函數(shù))的原型(prototype)屬性中,以便繼承正常工作。 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) 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'); // 調(diào)用Person的sayHello方法。 person1.sayHello(); // hello 在JavaScript中,方法是作為屬性被綁定到某個類/對象的普通函數(shù)對象,這意味著,可以“脫離上下文(out of the context)”來調(diào)用它們。考慮如下示例代碼: 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)”,因為該方法的所有引用都指向完全相同的函數(shù),即我們起初在原型上定義的那個函數(shù)。當某個函數(shù)被作為方法(或確切地說是屬性)調(diào)用時,JavaScript會將當前的“對象上下文(object context)”“綁定”到特定的“this”變量。這與調(diào)用該函數(shù)對象的“call”方法等效,如下所示: genderTeller.call(person1); //alerts 'Male'e 更多相關信息,請參閱Function.call和Function.apply 繼承(Inheritance) 繼承是一種方法,用于創(chuàng)建作為一個或多個類專用版本的類。(JavaScript僅支持單類繼承)。這個專用類通常被稱為子類(child),而其他類通常被稱為父類(parent)。在JavaScript中,你要完成繼承,需將父類的實例賦給子類,然后將子類特化(specializing)。 提示:由于JavaScript不檢測的子類的prototype.constructor(原型的構(gòu)造函數(shù)),參閱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() { //調(diào)用父類構(gòu)造函數(shù) Person.call(this); } // 繼承Person Student.prototype = new Person(); // 修正構(gòu)造函數(shù)指針,由于它指向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()方法是如何實現(xiàn)的,但仍可使用該方法;Student類無須顯式定義該方法,除非我們想改變它。這稱為封裝(encapsulation),這樣每個類繼承其父類的方法,并且只需定義它所希望改變的東西。 抽象 抽象是一種機制(mechanism),允許對處理中的問題的當前部分進行建模。這可以通過繼承(特化)或組合(composition)來實現(xiàn)。JavaScript通過繼承實現(xiàn)特化(specialization),通過讓類實例成為其他對象的屬性值實現(xiàn)組合。 var foo = function() {};
alert('foo is a Function: ' (foo instanceof Function)); alert('foo.prototype is an Object: ' (foo.prototype instanceof Object)); 多態(tài) 就像所有的方法和屬性被定義在原型屬性內(nèi)部一樣,不同的類可以定義具有相同名稱的方法;方法的作用域限于定義它們的類之內(nèi)。這僅當兩個類之間沒有父子關系(當一個類沒有從繼承鏈中的其他類繼承時)時才為真。 提示 本文中所提出的面向?qū)ο缶幊虒崿F(xiàn)技術不僅適用于JavaScript,因為就如何進行面向?qū)ο缶幊潭?,這是非常靈活的。 |
|
來自: 瀟湘雨plgwyaef > 《待分類》