概述 面向過程與面向對象面向過程:專註於如何去解決一個問題的過程,編程特點是用一個個函數去實現過程操作,沒有類與對象的概念面向對象:專註於有哪一個對象實體去解決這個問題,編程特點是:出現了一個個的類,由類去生成對象。面向對象的三大特征:繼承,封裝,多態 對象和類的概念 類是抽象的,對象是具體的(類是 ...
概述
面向過程與面向對象
面向過程:專註於如何去解決一個問題的過程,編程特點是用一個個函數去實現過程操作,沒有類與對象的概念
面向對象:專註於有哪一個對象實體去解決這個問題,編程特點是:出現了一個個的類,由類去生成對象。
面向對象的三大特征:繼承,封裝,多態
對象和類的概念
類是抽象的,對象是具體的(類是對象的抽象化,對象是類的具體化)
通俗的來講:類是一個抽象的概念,表示具有相同屬性和行為的集合,但是類僅僅表明這類群體具有相同的屬性,但是沒有具體的屬性值,而對象是對類的屬性進行具體賦值後得到的具體的個體
雖然JavaScript是一門面向對象編程語言,但它沒有提供class的語法支持。
在JavaScript中,一切都是基於對象的,即使後面要講的“原型”也都是對象,JavaScript的繼承和重用也都是通過原型來實現的。
但是結合構造函數和原型對象可以實現JavaScript的“類”。
構造函數
之前我們使用new Array()創建一個數組,使用new Object()創建一個對象,Array()和Object()是JavaScript內置的兩個構造函數,儘管JavaScript沒有提供類,但我們可以將Array和Object理解為“類”的概念。
需要註意的是,JavaScript的“類”是由構造函數實現的。
//定義一個類(構造函數) function Person(name,age,sex){ //類的屬性 this.name = name; this.age = age; this.sex = sex; }
使用構造函數
JavaScript使用類的方式和C#一樣,new關鍵字後面跟著構造函數。
var zhangsan = new Person("張三",18,"男"); zhangsan.say();
定義屬性和方法
現在我們已經定義好了Person類,可以為Person類添加一些屬性和方法。
定義屬性
在講JavaScript對象時,我們講了對象的屬性設置和訪問。
這段代碼展示了定義對象屬性的兩種方式:
function Person(){ //類的方法 this.say = function(){ alert("我叫"+this.name+",今年"+this.age+"歲,是一個"+this.sex+"生。") } }
使用this定義屬性
JavaScript類的屬性定義方式則有些不同,在構造函數中使用this關鍵字定義屬性:
function Person(name){ this.name = name; }
- 第一行代碼,定義了Person類,並定義了構造函數。
- 第二行代碼,定義了name屬性。
創建並使用對象
wangwu.say();
console.log(zhangsan.age)
constructor屬性
當創建一個對象時,一個特殊的屬性被JavaScript自動地分配給對象了,這個屬性就是constructor屬性。
在chrome控制台輸入p1.constructor
,可以看到p1對象的constructor屬性指向一個函數。
原型對象
在JavaScript中,定義一個函數時,函數就會擁有prototype屬性,構造函數也不例外。
下圖說明瞭Person()構造函數的prototype屬性是一個對象,它是屬於函數的,我們稱這個屬性為原型對象。
從Person類的角度出發,我們也可理解為prototype屬性是屬於Person類的。
設置prototype
既然prototype是一個對象,那就可以為它添加屬性和方法。
在函數的protpotype屬性上定義屬性和方法,與設置普通對象的屬性和方法沒什麼區別。
下麵的代碼為Person.prototype定義了屬性和方法。
Person.prototype.name4 = "name4";//原型屬性
自有屬性 和 prototype的屬性
首先,我們可以將Person類中的屬性和方法理解為“實例屬性”。
由於prototype是共用的,我們可以將prototype中的屬性和方法理解為“共用屬性”。
“實例屬性”和“共用屬性”的差別主要體現在性能上。
每創建一個Person的實例,就會產生一個name屬性和sayHello()方法的副本,而height屬性和run()方法則是所有實例共用一個副本。
既然如此,這意味著sayHello()方法可以提到prototype中。
另外,不同的Person實例height可能會不一樣,應將它放到Person類中更合理。
function Person(name,height){ this.name = name; this.height = height; } Person.prototype.say = function(){ return '我是' + this.name + ',我的身高是' + this.height; } Person.prototype.run = function(){ return '我是' + this.name + ',我在走路!'; } var p1 = new Person('張三',183); var p2 = new Person('李四',160);
類的實現總結
- JavaScript沒有類,但構造函數可以實現“類”。
- 按照JavaScript編程規範,構造函數的首字母應該大寫。
- “類”的屬性和方法是用
this.property
方式定義在構造函數中的。 - 在對象創建時JavaScript分配了
constructor
屬性給對象,constructor
屬性是對象構造函數的一個引用。 - 函數在定義時就已經有了
prototype
屬性,prototype
屬性也是一個對象。 - prototype是共用的,定義在
prototype
上的屬性和方法可以被“類”的實例使用。 - 如果屬性或方法能夠定義在
prototype
上,就不要定義在構造函數上,使用prototype
可以減少記憶體開銷。