先決條件: | 基本的計(jì)算機(jī)素養(yǎng),對(duì)HTML和CSS的基本了解,熟悉JavaScript基礎(chǔ)知識(shí)(請(qǐng)參見(jiàn)第一步和構(gòu)建塊 / a>)和OOJS基礎(chǔ)知識(shí)(請(qǐng)參見(jiàn)對(duì)象簡(jiǎn)介)。 |
---|---|
目的: | 要理解面向?qū)ο缶幊瘫澈蟮幕纠碚?,這是如何與JavaScript(“一切都是一個(gè)對(duì)象")有關(guān),以及如何創(chuàng)建構(gòu)造函數(shù)和對(duì)象實(shí)例。 |
首先,讓我們給出一個(gè)簡(jiǎn)單的,高級(jí)的面向?qū)ο缶幊?OOP)的視圖。 我們說(shuō)簡(jiǎn)單,因?yàn)镺OP可以很快變得非常復(fù)雜,現(xiàn)在給它一個(gè)完全的治療可能會(huì)混淆更多的幫助。 OOP的基本思想是,我們使用對(duì)象來(lái)模擬我們想要在程序中表示的現(xiàn)實(shí)世界中的事物,和/或提供一種簡(jiǎn)單的方法來(lái)訪問(wèn)否則難以或不可能使用的功能。
對(duì)象可以包含相關(guān)數(shù)據(jù)和代碼,它們表示有關(guān)您嘗試建模的信息,以及您希望它具有的功能或行為。 對(duì)象數(shù)據(jù)(通常也是函數(shù))可以在一個(gè)對(duì)象包(它可以被給定一個(gè)特定的名稱來(lái)引用,有時(shí)稱為)中整齊地存儲(chǔ)(官方單詞封裝 > namespace ),使其易于構(gòu)造和訪問(wèn); 對(duì)象也通常用作可以容易地通過(guò)網(wǎng)絡(luò)發(fā)送的數(shù)據(jù)存儲(chǔ)。
讓我們考慮一個(gè)簡(jiǎn)單的程序,顯示學(xué)校的學(xué)生和教師的信息。 這里我們將一般來(lái)看看OOP理論,而不是在任何特定的編程語(yǔ)言的上下文中。
要開(kāi)始此操作,我們可以從第一個(gè)對(duì)象文章返回到我們的Person對(duì)象類型,該文章定義了人員的通用數(shù)據(jù)和功能。 有很多東西你可以知道一個(gè)人(他們的地址,身高,鞋碼,DNA個(gè)人資料,護(hù)照號(hào)碼,重要的個(gè)性特征...),但在這種情況下,我們只感興趣 顯示他們的名字,年齡,性別和興趣,我們也希望能夠基于這些數(shù)據(jù)寫一個(gè)簡(jiǎn)短的介紹,并讓他們打招呼。 這被稱為抽象 - 創(chuàng)建一個(gè)更復(fù)雜的事情的簡(jiǎn)單模型,它以一種很容易與我們程序的目的一起使用的方式表示其最重要的方面。
>
在一些OOP語(yǔ)言中,這個(gè)通用對(duì)象類型定義被稱為類(JavaScript使用不同的機(jī)制和術(shù)語(yǔ),如下所示) - 它實(shí)際上不是對(duì)象,而是一個(gè) 模板,定義對(duì)象應(yīng)具有的特性。
從我們的類中,我們可以創(chuàng)建對(duì)象實(shí)例 - 包含類中定義的數(shù)據(jù)和功能的對(duì)象。 從我們的Person類,我們現(xiàn)在可以創(chuàng)建一些實(shí)際的人:
:700px;">
當(dāng)從類創(chuàng)建對(duì)象實(shí)例時(shí),將運(yùn)行類的構(gòu)造函數(shù)來(lái)創(chuàng)建它。 從類創(chuàng)建對(duì)象實(shí)例的過(guò)程稱為實(shí)例化 - 對(duì)象實(shí)例從類中實(shí)例化。
在這種情況下,我們不想要一般人 - 我們希望教師和學(xué)生,這兩種更具體類型的人。 在OOP中,我們可以基于其他類創(chuàng)建新類 - 這些新的子類可用于繼承其父類的數(shù)據(jù)和代碼功能 strong>,因此您可以重用所有對(duì)象類型通用的功能,而不必重復(fù)它。 在類之間的功能不同時(shí),您可以根據(jù)需要直接在其上定義特定功能。
:700px;">
這是非常有用的 - 教師和學(xué)生分享了許多常見(jiàn)的功能,如姓名,性別和年齡,所以只需要定義這些功能一次便利。 您還可以在不同的類中單獨(dú)定義相同的功能,因?yàn)樵摴δ艿拿總€(gè)定義都將位于不同的命名空間中。 例如,學(xué)生的問(wèn)候語(yǔ)可以是"Yo,I\'m [firstName]"(例如,
注意:對(duì)于多個(gè)對(duì)象類型實(shí)現(xiàn)相同功能的能力而言,多態(tài)性非常奇怪。 以防萬(wàn)一你想知道。
現(xiàn)在可以從子類創(chuàng)建對(duì)象實(shí)例。 例如:
; width:700px;">
在本文的其余部分,我們將開(kāi)始研究如何在JavaScript中實(shí)現(xiàn)OOP理論。
有些人認(rèn)為JavaScript不是一個(gè)真正的面向?qū)ο蟮恼Z(yǔ)言 - 例如它沒(méi)有用于創(chuàng)建像許多OO語(yǔ)言的類的 class
語(yǔ)句。 JavaScript使用稱為構(gòu)造函數(shù)的特殊函數(shù)來(lái)定義對(duì)象及其特征。 它們很有用,因?yàn)槟銜?huì)經(jīng)常遇到你不知道你將要?jiǎng)?chuàng)建多少對(duì)象的情況; 構(gòu)造函數(shù)提供了以有效方式創(chuàng)建任意數(shù)量對(duì)象的方法,根據(jù)需要將數(shù)據(jù)和函數(shù)附加到它們。
當(dāng)從構(gòu)造函數(shù)創(chuàng)建一個(gè)新的對(duì)象實(shí)例時(shí),并不是所有的功能都被復(fù)制到像"經(jīng)典"OO語(yǔ)言這樣的新對(duì)象,而是通過(guò)一個(gè)稱為原型鏈的引用鏈鏈接到該對(duì)象實(shí)例(參見(jiàn) "/ webstart / Objects / Object_prototypes">對(duì)象原型)。 所以這不是真正的實(shí)例化,嚴(yán)格來(lái)說(shuō) - JavaScript使用不同的機(jī)制在對(duì)象之間共享功能。
注意:不是"經(jīng)典OOP"不一定是壞事; 如上所述,OOP可以非常快速地得到非常復(fù)雜,JavaScript有一些不錯(cuò)的方法利用OO功能,而不必太深入。
讓我們探索通過(guò)構(gòu)造函數(shù)創(chuàng)建類并在JavaScript中從中創(chuàng)建對(duì)象實(shí)例。 首先,我們希望您創(chuàng)建一個(gè)新的本地副本 class ="external"> oojs.html 文件,我們?cè)诘谝黄狾bjects文章中看到。
function createNewPerson(name) { var obj = {}; obj.name = name; obj.greeting = function () { alert('Hi! I\'m ' + this.name + '.'); } return obj; }
var salva = createNewPerson('salva'); salva.name; salva.greeting();This works well enough, but it is a bit longwinded; if we know we want to create an object, why do we need to explicitly create a new empty object and return it? Fortunately JavaScript provides us with a handy shortcut, in the form of constructor functions — let's make one now!
function Person(name) { this.name = name; this.greeting = function() { alert('Hi! I\'m ' + this.name + '.'); }; }
構(gòu)造函數(shù)是JavaScript的一個(gè)類的版本。 你會(huì)注意到它有一個(gè)所有的功能,你期望在一個(gè)函數(shù),雖然它不返回任何東西或顯式創(chuàng)建一個(gè)對(duì)象 - 它基本上只是定義屬性和方法。 你會(huì)看到這里使用的 this
關(guān)鍵字 - 它基本上是說(shuō),無(wú)論何時(shí)創(chuàng)建這些對(duì)象實(shí)例之一,對(duì)象的 name
屬性將等于 傳遞給構(gòu)造函數(shù)調(diào)用的名稱值, greeting()
方法將使用傳遞給構(gòu)造函數(shù)調(diào)用的名稱值。
注意:構(gòu)造函數(shù)名稱通常以大寫字母開(kāi)頭 - 此約定用于使構(gòu)造函數(shù)在代碼中更易于識(shí)別。
那么我們?nèi)绾握{(diào)用構(gòu)造函數(shù)來(lái)創(chuàng)建一些對(duì)象呢?
var person1 = new Person('Bob'); var person2 = new Person('Sarah');
person1.name person1.greeting() person2.name person2.greeting()
涼! 現(xiàn)在,您將看到頁(yè)面上有兩個(gè)新對(duì)象,每個(gè)對(duì)象都存儲(chǔ)在不同的命名空間下 - 當(dāng)您訪問(wèn)其屬性和方法時(shí),必須使用 person1
或 > person2
; 他們整齊地打包,使他們不會(huì)與其他功能沖突。 但是它們具有相同的 name
屬性和 greeting()
方法。 注意,他們使用自己創(chuàng)建時(shí)分配給他們的 name
值; 這是為什么使用 this
非常重要的一個(gè)原因,所以他們將使用自己的值,而不是一些其他值。
讓我們?cè)倏纯礃?gòu)造函數(shù)調(diào)用:
var person1 = new Person('Bob'); var person2 = new Person('Sarah');
在每種情況下, new
關(guān)鍵字用于告訴瀏覽器我們要?jiǎng)?chuàng)建一個(gè)新的對(duì)象實(shí)例,后面跟著括號(hào)中包含其必需參數(shù)的函數(shù)名稱,結(jié)果存儲(chǔ)在變量中 - 非常類似于如何調(diào)用標(biāo)準(zhǔn)函數(shù)。 每個(gè)實(shí)例根據(jù)此定義創(chuàng)建:
function Person(name) { this.name = name; this.greeting = function() { alert('Hi! I\'m ' + this.name + '.'); }; }
創(chuàng)建新對(duì)象后, person1
和 person2
變量實(shí)際上包含以下對(duì)象:
{ name : 'Bob', greeting : function() { alert('Hi! I\'m ' + this.name + '.'); } } { name : 'Sarah', greeting : function() { alert('Hi! I\'m ' + this.name + '.'); } }
我們有效地說(shuō),因?yàn)閷?shí)際上,功能仍然在類中定義,而不是在對(duì)象實(shí)例,而不是我們前面看到的對(duì)象字面量。
我們上面看到的例子只是一個(gè)簡(jiǎn)單的例子,讓我們開(kāi)始。 讓我們開(kāi)始創(chuàng)建我們的最終 Person()
構(gòu)造函數(shù)。
function Person(first, last, age, gender, interests) { this.name = { first, last }; this.age = age; this.gender = gender; this.interests = interests; this.bio = function() { alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.'); }; this.greeting = function() { alert('Hi! I\'m ' + this.name.first + '.'); }; };
var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
現(xiàn)在您將看到,您可以像訪問(wèn)我們定義的第一個(gè)對(duì)象一樣訪問(wèn)屬性和方法:
person1['age'] person1.interests[1] person1.bio() // etc.
注意:如果您無(wú)法使用此工具,請(qǐng)嘗試將您的代碼與我們的版本進(jìn)行比較 - 請(qǐng)參閱 /javascript/oojs/introduction/oojs-class-finished.html"class ="external"> oojs-class-finished.html (也 -area / javascript / oojs / introduction / oojs-class-finished.html"class ="external">查看它正在運(yùn)行)。
首先,嘗試添加一些您自己的對(duì)象創(chuàng)建行,并嘗試獲取和設(shè)置生成的對(duì)象實(shí)例的成員。
此外,我們的 bio()
方法有一些問(wèn)題 - 輸出總是包括代詞"He",即使你的人是女性,或一些其他首選的性別分類。 并且bio將只包括兩個(gè)興趣,即使更多的興趣列在 interests
數(shù)組。 你能解決如何解決這個(gè)在類定義(構(gòu)造函數(shù))? 你可以把任何你喜歡的代碼放在構(gòu)造函數(shù)中(你可能需要一些條件和循環(huán))。 考慮如何根據(jù)性別,以及取決于所列出的興趣的數(shù)量是1,2還是多于2,句子應(yīng)該結(jié)構(gòu)不同。
注意:如果您遇到困難,我們提供了 -further-exercises.html"class ="external"> answer在我們的GitHub repo ( class-further-exercises.html"class ="external">看到它現(xiàn)場(chǎng)) - 嘗試自己首先寫它!
到目前為止,我們已經(jīng)看到了兩種創(chuàng)建對(duì)象實(shí)例的方法 - 聲明對(duì)象字面值,并使用構(gòu)造函數(shù)(參見(jiàn)上文)。
這些都是有意義的,但還有其他方法 - 我們希望讓您熟悉這些,以防萬(wàn)一您在網(wǎng)絡(luò)上的旅行中遇到它們。
首先,您可以使用 Object()
構(gòu)造函數(shù)創(chuàng)建一個(gè)新對(duì)象。 是的,即使通用對(duì)象有一個(gè)構(gòu)造函數(shù),它生成一個(gè)空對(duì)象。
var person1 = new Object();
person1
variable. You can then add properties and methods to this object using dot or bracket notation as desired; try these examples: person1.name = 'Chris'; person1['age'] = 38; person1.greeting = function() { alert('Hi! I\'m ' + this.name + '.'); }
Object()
constructor as a parameter, to prefill it with properties/methods. Try this: var person1 = new Object({ name : 'Chris', age : 38, greeting : function() { alert('Hi! I\'m ' + this.name + '.'); } });
JavaScript有一個(gè)內(nèi)置的方法 create()
a> ,它允許您基于現(xiàn)有對(duì)象創(chuàng)建新的對(duì)象實(shí)例。
var person2 = Object.create(person1);
person2.name person2.greeting()
您將看到基于 person1
創(chuàng)建的 person2
- 它具有相同的屬性和方法。 這是非常有用的,因?yàn)樗试S你創(chuàng)建新的對(duì)象實(shí)例,而不需要定義一個(gè)構(gòu)造函數(shù)。 缺點(diǎn)是 create()
不支持的瀏覽器早在構(gòu)造函數(shù)(IE9,而不是IE8甚至之前),加上一些think構(gòu)造函數(shù)給你的代碼更多的順序 - 你可以創(chuàng)建你的 構(gòu)造函數(shù)在一個(gè)地方,然后根據(jù)需要?jiǎng)?chuàng)建實(shí)例,并清楚它們來(lái)自哪里。
但是,如果你不太擔(dān)心支持真正舊的瀏覽器,并且你只需要一個(gè)對(duì)象的幾個(gè)副本,創(chuàng)建一個(gè)構(gòu)造函數(shù)可能是overkill的代碼。 這取決于你喜歡什么。 有些人只是發(fā)現(xiàn) create()
更容易理解和使用。
我們將在后面更詳細(xì)地探討 create()
的效果。
本文提供了面向?qū)ο罄碚摰暮?jiǎn)化視圖 - 這不是全部的故事,但它給了我們?cè)谶@里處理我們的想法。 此外,我們已經(jīng)開(kāi)始看看JavaScript如何與"經(jīng)典OOP",如何使用構(gòu)造函數(shù)在JavaScript中實(shí)現(xiàn)類以及生成對(duì)象實(shí)例的不同方式有所不同。
在下一篇文章中,我們將探討JavaScript對(duì)象原型。
更多建議: