加勒比HEZYO黑人专区-久久精品国产99国产精品亚洲-精品国产18久久久久久-久久人妻少妇嫩草AV

歡迎光臨 織晶網(wǎng)絡(luò)官網(wǎng)!

  • 服務(wù)支持
  • 020-39182790
技術(shù)文檔您現(xiàn)在的位置:首頁(yè) > 服務(wù)支持 > 技術(shù)文檔

JavaScript面向?qū)ο蠛?jiǎn)介

作者:織晶客服部   發(fā)布于:2016/7/27 15:24:23  點(diǎn)擊量:  來(lái)源:織晶網(wǎng)絡(luò)

JavaScript 的核心是支持面向?qū)ο蟮模瑫r(shí)它也提供了強(qiáng)大靈活的 OOP 語(yǔ)言能力。本文從對(duì)面向?qū)ο缶幊痰慕榻B開始,帶您探索 JavaScript 的對(duì)象模型,最后描述 JavaScript 當(dāng)中面向?qū)ο缶幊痰囊恍└拍睢?


JavaScript回顧

如果您對(duì) JavaScript 的概念(如變量、類型、方法和作用域等)缺乏自信,您可以在重新介紹 JavaScript 這篇文章里學(xué)習(xí)這些概念。您也可以查閱這篇 JavaScript 1.5 核心指南。


面向?qū)ο缶幊?/strong>

面向?qū)ο缶幊淌怯贸橄蠓绞絼?chuàng)建基于現(xiàn)實(shí)世界模型的一種編程模式。它使用先前建立的范例,包括模塊化,多態(tài)和封裝幾種技術(shù)。今天,許多流行的編程語(yǔ)言(如Java,JavaScript,C#,C+ +,Python,PHP,Ruby和Objective-C)都支持面向?qū)ο缶幊蹋∣OP)。


面向?qū)ο缶幊炭梢钥醋魇鞘褂靡幌盗袑?duì)象相互協(xié)作的軟件設(shè)計(jì),相對(duì)于傳統(tǒng)觀念,一個(gè)程序只是一些函數(shù)的集合,或簡(jiǎn)單的計(jì)算機(jī)指令列表。 在OOP中,每個(gè)對(duì)象能夠接收消息,處理數(shù)據(jù)和發(fā)送消息給其他對(duì)象。每個(gè)對(duì)象都可以被看作是一個(gè)擁有清晰角色或責(zé)任的獨(dú)立小機(jī)器。


面向?qū)ο蟪绦蛟O(shè)計(jì)的目的是在編程中促進(jìn)更好的靈活性和可維護(hù)性,在大型軟件工程中廣為流行。憑借其對(duì)模塊化的重視,面向?qū)ο蟮拇a開發(fā)更簡(jiǎn)單,更容易理解,相比非模塊化編程方法 1, 它能更直接地分析, 編碼和理解復(fù)雜的情況和過(guò)程。


術(shù)語(yǔ)

Namespace 命名空間

允許開發(fā)人員在一個(gè)獨(dú)特, 應(yīng)用相關(guān)的名字的名稱下捆綁所有功能的容器。

Class 類

定義對(duì)象的特征。它是對(duì)象的屬性和方法的模板定義.

Object 對(duì)象

類的一個(gè)實(shí)例。

Property 屬性

對(duì)象的特征,比如顏色。

Method 方法

對(duì)象的能力,比如行走。

Constructor 構(gòu)造函數(shù)

對(duì)象初始化的瞬間, 被調(diào)用的方法. 通常它的名字與包含它的類一致.

Inheritance 繼承

一個(gè)類可以繼承另一個(gè)類的特征。

Encapsulation 封裝

一種把數(shù)據(jù)和相關(guān)的方法綁定在一起使用的方法.

Abstraction 抽象

結(jié)合復(fù)雜的繼承,方法,屬性的對(duì)象能夠模擬現(xiàn)實(shí)的模型。

Polymorphism 多態(tài)

多意為‘許多’,態(tài)意為‘形態(tài)’。不同類可以定義相同的方法或?qū)傩浴?

更多關(guān)于面向?qū)ο缶幊痰拿枋觯?qǐng)參照維基百科的 面向?qū)ο缶幊?。


原型編程

基于原型的編程不是面向?qū)ο缶幊讨畜w現(xiàn)的風(fēng)格,且行為重用(在基于類的語(yǔ)言中也稱為繼承)是通過(guò)裝飾它作為原型的現(xiàn)有對(duì)象的過(guò)程實(shí)現(xiàn)的。這種模式也被稱為弱類化,原型化,或基于實(shí)例的編程。


原始的(也是最典型的)基于原型語(yǔ)言的例子是由大衛(wèi)·安格爾和蘭德爾·史密斯開發(fā)的。然而,弱類化的編程風(fēng)格近來(lái)變得越來(lái)越流行,并已被諸如JavaScript,Cecil,NewtonScript,IO,MOO,REBOL,Kevo,Squeak(使用框架操縱Morphic組件),和其他幾種編程語(yǔ)言采用。1


JavaScript面向?qū)ο缶幊?/span>

命名空間

命名空間是一個(gè)容器,它允許開發(fā)人員在一個(gè)獨(dú)特的,特定于應(yīng)用程序的名稱下捆綁所有的功能。 在JavaScript中,命名空間只是另一個(gè)包含方法,屬性,對(duì)象的對(duì)象。

注意:需要認(rèn)識(shí)到重要的一點(diǎn)是:與其他面向?qū)ο缶幊陶Z(yǔ)言不同的是,Javascript中的普通對(duì)象和命名空間在語(yǔ)言層面上沒(méi)有區(qū)別。這點(diǎn)可能會(huì)讓JavaScript初學(xué)者感到迷惑。


創(chuàng)造的JavaScript命名空間背后的想法很簡(jiǎn)單:一個(gè)全局對(duì)象被創(chuàng)建,所有的變量,方法和功能成為該對(duì)象的屬性。使用命名空間也最大程度地減少應(yīng)用程序的名稱沖突的可能性。


我們來(lái)創(chuàng)建一個(gè)全局變量叫做 MYAPP

// 全局命名空間

var MYAPP = MYAPP || {};

在上面的代碼示例中,我們首先檢查MYAPP是否已經(jīng)被定義(是否在同一文件中或在另一文件)。如果是的話,那么使用現(xiàn)有的MYAPP全局對(duì)象,否則,創(chuàng)建一個(gè)名為MYAPP的空對(duì)象用來(lái)封裝方法,函數(shù),變量和對(duì)象。


我們也可以創(chuàng)建子命名空間:

// 子命名空間

MYAPP.event = {};

下面是用于創(chuàng)建命名空間和添加變量,函數(shù)和方法的代碼寫法:

// 給普通方法和屬性創(chuàng)建一個(gè)叫做MYAPP.commonMethod的容器

MYAPP.commonMethod = {

regExForName: "", // 定義名字的正則驗(yàn)證

regExForPhone: "", // 定義電話的正則驗(yàn)證

validateName: function(name){

// 對(duì)名字name做些操作,你可以通過(guò)使用“this.regExForname”

// 訪問(wèn)regExForName變量

},

validatePhoneNo: function(phoneNo){

// 對(duì)電話號(hào)碼做操作

}

}

// 對(duì)象和方法一起申明

MYAPP.event = {

addListener: function(el, type, fn) {

// 代碼

},

removeListener: function(el, type, fn) {

// 代碼

},

getEvent: function(e) {

// 代碼

}

// 還可以添加其他的屬性和方法

}

//使用addListner方法的寫法:

MYAPP.event.addListener("yourel", "type", callback);


標(biāo)準(zhǔn)內(nèi)置對(duì)象

JavaScript有包括在其核心的幾個(gè)對(duì)象,例如,Math,Object,Array和String對(duì)象。下面的例子演示了如何使用Math對(duì)象的random()方法來(lái)獲得一個(gè)隨機(jī)數(shù)。

console.log(Math.random());

注意:T這里和接下來(lái)的例子都假設(shè)名為 console.log 的方法全局有定義。console.log 實(shí)際上不是 JavaScript 自帶的。

查看 JavaScript 參考:全局對(duì)象 了解 JavaScript 內(nèi)置對(duì)象的列表。

JavaScript 中的每個(gè)對(duì)象都是 Object 對(duì)象的實(shí)例且繼承它所有的屬性和方法。


自定義對(duì)象


JavaScript是一種基于原型的語(yǔ)言,它沒(méi)類的聲明語(yǔ)句,比如C+ +或Java中用的。這有時(shí)會(huì)對(duì)習(xí)慣使用有類申明語(yǔ)句語(yǔ)言的程序員產(chǎn)生困擾。相反,JavaScript可用方法作類。定義一個(gè)類跟定義一個(gè)函數(shù)一樣簡(jiǎn)單。在下面的例子中,我們定義了一個(gè)新類Person。


function Person() { }

// 或

var Person = function(){ }


對(duì)象(類的實(shí)例)

我們使用 new obj 創(chuàng)建對(duì)象 obj 的新實(shí)例, 將結(jié)果(obj 類型)賦值給一個(gè)變量方便稍后調(diào)用。


在下面的示例中,我們定義了一個(gè)名為Person的類,然后我們創(chuàng)建了兩個(gè)Person的實(shí)例(person1 and person2).

function Person() { }

var person1 = new Person();

var person2 = new Person();

注意:有一種新增的創(chuàng)建未初始化實(shí)例的實(shí)例化方法,請(qǐng)參考 Object.create 。


構(gòu)造器

在實(shí)例化時(shí)構(gòu)造器被調(diào)用 (也就是對(duì)象實(shí)例被創(chuàng)建時(shí))。構(gòu)造器是對(duì)象中的一個(gè)方法。 在JavaScript,中函數(shù)就可以作為構(gòu)造器使用,因此不需要特別地定義一個(gè)構(gòu)造器方法. 每個(gè)聲明的函數(shù)都可以在實(shí)例化后被調(diào)用執(zhí)行


構(gòu)造器常用于給對(duì)象的屬性賦值或者為調(diào)用函數(shù)做準(zhǔn)備。 在本文的后面描述了類中方法既可以在定義時(shí)添加,也可以在使用前添加。


在下面的示例中, Person類實(shí)例化時(shí)構(gòu)造器調(diào)用一個(gè) alert函數(shù)。

function Person() {

alert('Person instantiated');

}


var person1 = new Person();

var person2 = new Person();


屬性 (對(duì)象屬性)

屬性就是 類中包含的變量;每一個(gè)對(duì)象實(shí)例有若干個(gè)屬性. 為了正確的繼承,屬性應(yīng)該被定義在類的原型屬性 (函數(shù))中。


可以使用 關(guān)鍵字 this調(diào)用類中的屬性, this是對(duì)當(dāng)前對(duì)象的引用。 從外部存取(讀/寫)其屬性的語(yǔ)法是: InstanceName.Property; 這與C++,Java或者許多其他語(yǔ)言中的語(yǔ)法是一樣的 (在類中語(yǔ)法 this.Property 常用于set和get屬性值)


在下面的示例中,我們?yōu)槎xPerson類定義了一個(gè)屬性 firstName 并在實(shí)例化時(shí)賦初值。

function Person(firstName) {

this.firstName = firstName;

alert('Person instantiated');

}


var person1 = new Person('Alice');

var person2 = new Person('Bob');


// Show the firstName properties of the objects

alert('person1 is ' + person1.firstName); // alerts "person1 is Alice"

alert('person2 is ' + person2.firstName); // alerts "person2 is Bob"


方法(對(duì)象屬性)

方法與屬性很相似, 不同的是:一個(gè)是函數(shù),另一個(gè)可以被定義為函數(shù)。 調(diào)用方法很像存取一個(gè)屬性, 不同的是add () 在方法名后面很可能帶著參數(shù). 為定義一個(gè)方法, 需要將一個(gè)函數(shù)賦值給類的 prototype 屬性; 這個(gè)賦值給函數(shù)的名稱就是用來(lái)給對(duì)象在外部調(diào)用它使用的。


在下面的示例中,我們給Person類定義了方法 sayHello(),并調(diào)用了它.

function Person(firstName) {

this.firstName = firstName;

}


Person.prototype.sayHello = function() {

alert("Hello, I'm " + this.firstName);

};


var person1 = new Person("Alice");

var person2 = new Person("Bob");


// call the Person sayHello method.

person1.sayHello(); // alerts "Hello, I'm Alice"

person2.sayHello(); // alerts "Hello, I'm Bob"

在JavaScript中方法通常是一個(gè)綁定到對(duì)象中的普通函數(shù), 這意味著方法可以在其所在context之外被調(diào)用。 思考下面示例中的代碼:

function Person(firstName) {

this.firstName = firstName;

}


Person.prototype.sayHello = function() {

alert("Hello, I'm " + this.firstName);

};


var person1 = new Person("Alice");

var person2 = new Person("Bob");

var helloFunction = person1.sayHello;


person1.sayHello(); // alerts "Hello, I'm Alice"

person2.sayHello(); // alerts "Hello, I'm Bob"

helloFunction();

// alerts "Hello, I'm undefined" (or fails

// with a TypeError in strict mode)

alert(helloFunction === person1.sayHello);

// alerts true

alert(helloFunction === Person.prototype.sayHello);

// alerts true

helloFunction.call(person1);

// alerts "Hello, I'm Alice"


如上例所示, 所有指向sayHello函數(shù)的引用 ,包括 person1, Person.prototype, 和 helloFunction 等, 均引用了相同的函數(shù).


在調(diào)用函數(shù)的過(guò)程中,this的值取決于我們?cè)趺礃诱{(diào)用函數(shù). 在通常情況下,我們通過(guò)一個(gè)表達(dá)式person1.sayHello()來(lái)調(diào)用函數(shù):即從一個(gè)對(duì)象的屬性中得到所調(diào)用的函數(shù)。此時(shí)this被設(shè)置為我們?nèi)〉煤瘮?shù)的對(duì)象(即person1)。這就是為什么person1.sayHello() 使用了姓名“Alice”而person2.sayHello()使用了姓名“bob”的原因。


然而我們使用不同的調(diào)用方法時(shí), this的值也就不同了。當(dāng)從變量 helloFunction()中調(diào)用的時(shí)候, this就被設(shè)置成了全局對(duì)象 (在瀏覽器中即window)。由于該對(duì)象 (非常可能地) 沒(méi)有firstName 屬性, 我們得到的結(jié)果便是"Hello, I'm undefined". (這是松散模式下的結(jié)果, 在 嚴(yán)格模式中,結(jié)果將不同(此時(shí)會(huì)產(chǎn)生一個(gè)error)。 但是為了避免混淆,我們?cè)谶@里不涉及細(xì)節(jié)) 。另外,我們可以像上例末尾那樣,使用Function#call (或者Function#apply)顯式的設(shè)置this的值。

更多有關(guān)信息請(qǐng)參考 Function#call and Function#apply


繼承

創(chuàng)建一個(gè)或多個(gè)類的專門版本類方式稱為繼承(Javascript只支持單繼承)。 創(chuàng)建的專門版本的類通常叫做子類,另外的類通常叫做父類。 在Javascript中,繼承通過(guò)賦予子類一個(gè)父類的實(shí)例并專門化子類來(lái)實(shí)現(xiàn)。在現(xiàn)代瀏覽器中你可以使用 Object.create 實(shí)現(xiàn)繼承.

JavaScript 并不檢測(cè)子類的 prototype.constructor (見 Object.prototype), 所以我們必須手動(dòng)申明它.

在下面的例子中, 我們定義了 Student類作為 Person類的子類. 之后我們重定義了sayHello() 方法并添加了 sayGoodBye() 方法.

// 定義Person構(gòu)造器

function Person(firstName) {

this.firstName = firstName;

}


// 在Person.prototype中加入方法

Person.prototype.walk = function(){

alert("I am walking!");

};

Person.prototype.sayHello = function(){

alert("Hello, I'm " + this.firstName);

};


// 定義Student構(gòu)造器

function Student(firstName, subject) {

// 調(diào)用父類構(gòu)造器, 確保(使用Function#call)"this" 在調(diào)用過(guò)程中設(shè)置正確

Person.call(this, firstName);


// 初始化Student類特有屬性

this.subject = subject;

};


// 建立一個(gè)由Person.prototype繼承而來(lái)的Student.prototype對(duì)象.

// 注意: 常見的錯(cuò)誤是使用 "new Person()"來(lái)建立Student.prototype.

// 這樣做的錯(cuò)誤之處有很多, 最重要的一點(diǎn)是我們?cè)趯?shí)例化時(shí)

// 不能賦予Person類任何的FirstName參數(shù)

// 調(diào)用Person的正確位置如下,我們從Student中來(lái)調(diào)用它

Student.prototype = Object.create(Person.prototype);

// See note below


// 設(shè)置"constructor" 屬性指向Student

Student.prototype.constructor = Student;


// 更換"sayHello" 方法

Student.prototype.sayHello = function(){

alert("Hello, I'm " + this.firstName + ". I'm studying " + this.subject + ".");

};


// 加入"sayGoodBye" 方法

Student.prototype.sayGoodBye = function(){

alert("Goodbye!");

};


// 測(cè)試實(shí)例:

var student1 = new Student("Janet", "Applied Physics");

student1.sayHello();

// "Hello, I'm Janet. I'm studying Applied Physics."

student1.walk();

// "I am walking!"

student1.sayGoodBye();

// "Goodbye!"


// Check that instanceof works correctly

alert(student1 instanceof Person);

// true

alert(student1 instanceof Student);

// true

對(duì)于“Student.prototype = Object.create(Person.prototype);”這一行,在不支持 Object.create方法的老JavaScript引擎中,可以使用一個(gè)"polyfill"(又名"shim",查看文章鏈接),或者使用一個(gè)function來(lái)獲得相同的返回值,就像下面:

function createObject(proto) {

function ctor() { }

ctor.prototype = proto;

return new ctor();

}


// Usage:

Student.prototype = createObject(Person.prototype);

更多相關(guān)信息請(qǐng)參考 Object.create,連接中還有一個(gè)老JavaScript引擎的兼容方案(shim)。

封裝

在上一個(gè)例子中,Student類雖然不需要知道Person類的walk()方法是如何實(shí)現(xiàn)的,但是仍然可以使用這個(gè)方法;Student類不需要明確地定義這個(gè)方法,除非我們想改變它。 這就叫做封裝,對(duì)于所有繼承自父類的方法,只需要在子類中定義那些你想改變的即可。


抽象

抽象是允許模擬工作問(wèn)題中通用部分的一種機(jī)制。這可以通過(guò)繼承(具體化)或組合來(lái)實(shí)現(xiàn)。

JavaScript通過(guò)繼承實(shí)現(xiàn)具體化,通過(guò)讓類的實(shí)例是其他對(duì)象的屬性值來(lái)實(shí)現(xiàn)組合。


JavaScript Function 類繼承自O(shè)bject類(這是典型的具體化) 。Function.prototype的屬性是一個(gè)Object實(shí)例(這是典型的組合)。

var foo = function(){};

alert( 'foo is a Function: ' + (foo instanceof Function) );

// alerts "foo is a Function: true"

alert( 'foo.prototype is an Object: ' + (foo.prototype instanceof Object) );

// alerts "foo.prototype is an Object: true"


多態(tài)

就像所有定義在原型屬性內(nèi)部的方法和屬性一樣,不同的類可以定義具有相同名稱的方法;方法是作用于所在的類中。并且這僅在兩個(gè)類不是父子關(guān)系時(shí)成立(繼承鏈中,一個(gè)類不是繼承自其他類)。


注意

本文中所展示的面向?qū)ο缶幊碳夹g(shù)不是唯一的實(shí)現(xiàn)方式,在JavaScript中面向?qū)ο蟮膶?shí)現(xiàn)是非常靈活的。


同樣的,文中展示的技術(shù)沒(méi)有使用任何語(yǔ)言hacks,它們也沒(méi)有模仿其他語(yǔ)言的對(duì)象理論實(shí)現(xiàn)。


JavaScript中還有其他一些更加先進(jìn)的面向?qū)ο蠹夹g(shù),但這些都超出了本文的介紹范圍。




上一篇:PHP與MYSQL事務(wù)處理

下一篇:前端JavaScript 正則表達(dá)式語(yǔ)法