面向對象編程介紹
ES6 中的類和對象
類的繼承
面向對象案例
1. 面向對象編程介紹
1.1 兩大編程思想
面向過程:分析出解決問題所需要的步驟,然后用函數把這些步驟一步一步實現,使用的時候再一個一個的依 次調用就可以了。
面向對象:把事務分解成為一個個對象,然后由對象之間分工與合作。
1.3 面向對象編程 OOP (Object Oriented Programming)
在面向對象程序開發思想中,每一個對象都是功能中心,具有明確分工。 面向對象編程具有靈活、代碼可復用、容易維護和開發的優點,更適合多人合作的大型軟件項目。
面向對象的特性: 封裝性
繼承性
多態性
2. ES6 中的類和對象
面向對象
面向對象的思維特點:
1. 抽取(抽象)對象共用的屬性和行為組織(封裝)成一個類(模板)
2. 對類進行實例化, 獲取類的對象
2.1 對象
在 JavaScript 中,對象是一組無序的相關屬性和方法的集合,所有的事物都是對象,例如字符串、數值、數組、 函數等。
對象是由屬性和方法組成的:
屬性:事物的特征,在對象中用屬性來表示(常用名詞)
方法:事物的行為,在對象中用方法來表示(常用動詞)
2.2 類 class
在 ES6 中新增加了類的概念,可以使用 class 關鍵字聲明一個類,之后以這個類來實例化對象。
類抽象了對象的公共部分,它泛指某一大類(class)
對象特指某一個,通過類實例化一個具體的對象
2.3 創建類
語法:
class name { // class body }
創建實例:
var XX = new name();
注意: 類必須使用 new 實例化對象
2.4 類 constructor 構造函數
constructor() 方法是類的構造函數(默認方法),用於傳遞參數,返回實例對象,
通過 new 命令生成對象實例時 ,自動調用該構造函數。
如果沒有顯示定義, 類內部會自動給我們創建一個constructor()
// 1. 創建類 class 創建一個 明星類 class Star { constructor(uname, age) { this.uname = uname; this.age = age; } } // 2. 利用類創建對象 new var ldh = new Star('劉德華', 18); var zxy = new Star('張學友', 20); console.log(ldh); console.log(zxy); //(1) 通過class 關鍵字創建類, 類名我們還是習慣性定義首字母大寫 //(2) 類里面有個constructor 函數,可以接受傳遞過來的參數,同時返回實例對象 //(3) constructor 函數 只要 new 生成實例時,就會自動調用這個函數, 如果我們不寫這個函數,類也會自動生成這個函數 //(4) 生成實例 new 不能省略 //(5) 最后注意語法規范, 創建類 類名后面不要加小括號,生成實例 類名后面加小括號, 構造函數不需要加function
2.5 類添加方法
class Person { constructor(name,age) { // constructor 構造器或者構造函數 this.name = name; this.age = age; } say() { console.log(this.name + '你好'); } } //創建實例: var ldh = new Person('劉德華', 18); ldh.say()
3. 類的繼承
3.1 繼承
現實中的繼承:子承父業,比如我們都繼承了父親的姓。 程序中的繼承:子類可以繼承父類的一些屬性和方法。
語法:
class Father{ // 父類 } class Son extends Father { // 子類繼承父類 }
class Father { constructor(surname) { this.surname= surname; } say() { console.log('你的姓是' + this.surname); } } class Son extends Father{ // 這樣子類就繼承了父類的屬性和方法 } var damao= new Son('劉'); damao.say();
3.2 super 關鍵字
super 關鍵字用於訪問和調用對象父類上的函數。可以調用父類的構造函數,也可以調用父類的普通函數
調用父類的構造函數:
class Person { // 父類 constructor(surname){ this.surname = surname; } } class Student extends Person { // 子類繼承父類 constructor(surname,firstname){ super(surname); // 調用父類的constructor(surname) this.firstname = firstname; // 定義子類獨有的屬性 } }
調用父類的普通函數:
class Father { say() { return '我是爸爸'; } } class Son extends Father { // 這樣子類就繼承了父類的屬性和方法 say() { // super.say() super 調用父類的方法 return super.say() + '的兒子'; } } var damao = new Son(); console.log(damao.say());
三個注意點:
1. 在 ES6 中類沒有變量提升,所以必須先定義類,才能通過類實例化對象.
2. 類里面的共有屬性和方法一定要加this使用.
3. 類里面的this指向問題.
4. constructor 里面的this指向實例對象, 方法里面的this 指向這個方法的調用者
假如類里面的一個方法sing(){),在構造函數中通過 this.btn.onclick=this.sing;,這個sing方法的調用者是btn,而不是實例對象,因此sing方法里面的this指向的是btn
<button>點擊</button> <script> var that; var _that; class Star { constructor(uname, age) { // constructor 里面的this 指向的是 創建的實例對象 that = this; // 這句話將that也指向和this一樣的實例化對象 console.log(this); this.uname = uname; this.age = age; // this.sing(); this.btn = document.querySelector('button'); this.btn.onclick = this.sing; // 調用了sing方法 } sing() { // 這個sing方法里面的this 指向的是 btn 這個按鈕,因為這個按鈕調用了這個函數 console.log(this); // 如果想調用實例化對象的this,就可以使用上面的全局變量,從而調用構造函數里面的屬性 console.log(that.uname); // that里面存儲的是constructor里面的this } dance() { // 這個dance里面的this 指向的是實例對象 ldh 因為ldh 調用了這個函數 _that = this; console.log(this); } } var ldh = new Star('劉德華'); console.log(that === ldh); ldh.dance(); console.log(_that === ldh); // 1. 在 ES6 中類沒有變量提升,所以必須先定義類,才能通過類實例化對象 // 2. 類里面的共有的屬性和方法一定要加this使用. </script>