JavaScript高級-類的使用

  • 2021 年 2 月 18 日
  • 筆記

1.面向過程與面向對象

1.1面向過程

  • 面向過程就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候再一個一個的依次調用就可以了。

1.2面向對象

  • 面向對象是把事務分解成為一個個對象,然後由對象之間分工與合作。

1.3面向過程與面向對象對比

  面向過程 面向對象
優點 性能比面向對象高,適合跟硬體聯繫很緊密的東西,例如單片機就採用的面向過程編程。 易維護、易復用、易擴展,由於面向對象有封裝、繼承、多態性的特性,可以設計出低耦合的系統,使系統 更加靈活、更加易於維護
缺點 不易維護、不易復用、不易擴展 性能比面向過程低

2.對象與類

2.1對象

對象是由屬性和方法組成的:是一個無序鍵值對的集合,指的是一個具體的事物

  • 屬性:事物的特徵,在對象中用屬性來表示(常用名詞)
  • 方法:事物的行為,在對象中用方法來表示(常用動詞)

2.1.1創建對象

//以下程式碼是對對象的複習
//字面量創建對象
var ldh = {
    name: '劉德華',
    age: 18
}
console.log(ldh);

//構造函數創建對象
  function Star(name, age) {
    this.name = name;
    this.age = age;
 }
var ldh = new Star('劉德華', 18)//實例化對象
console.log(ldh);	

如上兩行程式碼運行結果為:
在這裡插入圖片描述

2.2類

  • 在 ES6 中新增加了類的概念,可以使用 class 關鍵字聲明一個類,之後以這個類來實例化對象。類抽象了對象的公共部分,它泛指某一大類(class)對象特指某一個,通過類實例化一個具體的對象

2.2.1創建類

  1. 語法:
//步驟1 使用class關鍵字
class name {
  // class body
}     
//步驟2使用定義的類創建實例  注意new關鍵字
var xx = new name();     
  1. 示例
 // 1. 創建類 class  創建一個 明星類
 class Star {
   // 類的共有屬性放到 constructor 裡面
   constructor(name, age) {
   this.name = name;
   this.age = age;
   }
 }
   // 2. 利用類創建對象 new
   var ldh = new Star('劉德華', 18);
   console.log(ldh);

以上程式碼運行結果:

在這裡插入圖片描述

通過結果我們可以看出,運行結果和使用構造函數方式一樣

2.2.2類創建添加屬性和方法

 // 1. 創建類 class  創建一個類
class Star {
    // 類的共有屬性放到 constructor 裡面 constructor是 構造器或者構造函數
    constructor(uname, age) {
      this.uname = uname;
      this.age = age;
    }//------------------------------------------->注意,方法與方法之間不需要添加逗號
    sing(song) {
      console.log(this.uname + '唱' + song);
    }
}
// 2. 利用類創建對象 new
var ldh = new Star('劉德華', 18);
console.log(ldh); // Star {uname: "劉德華", age: 18}
ldh.sing('冰雨'); // 劉德華唱冰雨

以上程式碼運行結果:

在這裡插入圖片描述

注意喲:

  1. 通過class 關鍵字創建類, 類名我們還是習慣性定義首字母大寫
  2. 類裡面有個constructor 函數,可以接受傳遞過來的參數,同時返回實例對象
  3. constructor 函數 只要 new 生成實例時,就會自動調用這個函數, 如果我們不寫這個函數,類也會自動生成這個函數
  4. 多個函數方法之間不需要添加逗號分隔
  5. 生成實例 new 不能省略
  6. 語法規範, 創建類 類名後面不要加小括弧,生成實例 類名後面加小括弧, 構造函數不需要加function

2.2.3類的繼承

  1. 語法
// 父類
class Father{   
} 

// 子類繼承父類
class  Son  extends Father {  
}       
  1. 示例
class Father {
      constructor(surname) {
        this.surname= surname;
      }
      say() {
        console.log('你的姓是' + this.surname);
       }
}

class Son extends Father{  // 這樣子類就繼承了父類的屬性和方法
}
var damao= new Son('劉');
damao.say();      //結果為 你的姓是劉

以上程式碼運行結果:

在這裡插入圖片描述

  • 子類使用super關鍵字訪問父類的方法

    //定義了父類
    class Father {
       constructor(x, y) {
       this.x = x;
       this.y = y;
       }
       sum() {
       console.log(this.x + this.y);
    	}
     }
    //子元素繼承父類
        class Son extends Father {
       		 constructor(x, y) {
        		super(x, y); //使用super調用了父類中的構造函數
        	}
        }
        var son = new Son(1, 2);
        son.sum(); //結果為3
    

    注意:

    1. 繼承中,如果實例化子類輸出一個方法,先看子類有沒有這個方法,如果有就先執行子類的

    2. 繼承中,如果子類裡面沒有,就去查找父類有沒有這個方法,如果有,就執行父類的這個方法(就近原則)

    3. 如果子類想要繼承父類的方法,同時在自己內部擴展自己的方法,利用super 調用父類的構造函數,super 必須在子類this之前調用

       // 父類有加法方法
       class Father {
         constructor(x, y) {
         this.x = x;
         this.y = y;
         }
         sum() {
         console.log(this.x + this.y);
         }
       }
       // 子類繼承父類加法方法 同時 擴展減法方法
       class Son extends Father {
         constructor(x, y) {
         // 利用super 調用父類的構造函數 super 必須在子類this之前調用,放到this之後會報錯
         super(x, y);
         this.x = x;
         this.y = y;
      
        }
        subtract() {
        console.log(this.x - this.y);
        }
      }
      var son = new Son(5, 3);
      son.subtract(); //2
      son.sum();//8
      

      以上程式碼運行結果為:

在這裡插入圖片描述

  1. 時刻注意this的指向問題,裡面的共有的屬性和方法一定要加this使用.

    1. constructor中的this指向的是new出來的實例對象
    2. 自定義的方法,一般也指向的new出來的實例對象
    3. 綁定事件之後this指向的就是觸發事件的事件源
  2. 在 ES6 中類沒有變數提升,所以必須先定義類,才能通過類實例化對象
    在這裡插入圖片描述

在這裡插入圖片描述

3.面向對象版tab 欄切換

3.1功能需求

  1. 點擊 tab欄,可以切換效果.
  2. 點擊 + 號, 可以添加 tab 項和內容項.
  3. 點擊 x 號, 可以刪除當前的tab項和內容項.
  4. 雙擊tab項文字或者內容項文字可以修改裡面的文字內容

3.2案例準備

  1. 獲取到標題元素
  2. 獲取到內容元素
  3. 獲取到刪除的小按鈕 x號
  4. 新建js文件,定義類,添加需要的屬性方法(切換,刪除,增加,修改)
  5. 時刻注意this的指向問題

3.3切換

  • 為獲取到的標題綁定點擊事件,展示對應的內容區域,存儲對應的索引

     this.lis[i].index = i;
     this.lis[i].onclick = this.toggleTab;
    
  • 使用排他,實現只有一個元素的顯示

     toggleTab() {
       //將所有的標題與內容類樣式全部移除
         for (var i = 0; i < this.lis.length; i++) {
         this.lis[i].className = '';
         this.sections[i].className = '';
         }
       //為當前的標題添加激活樣式
         this.className = 'liactive';
        //為當前的內容添加激活樣式
         that.sections[this.index].className = 'conactive';
      }
    

3.4添加

  • 為添加按鈕+ 綁定點擊事件

     this.add.onclick = this.addTab;
    
  • 實現標題與內容的添加,做好排他處理

    addTab() {
        that.clearClass();
        // (1) 創建li元素和section元素 
        var random = Math.random();
        var li = '<li class="liactive"><span>新選項卡</span><span class="iconfont icon-guanbi">				</span></li>';
        var section = '<section class="conactive">測試 ' + random + '</section>';
        // (2) 把這兩個元素追加到對應的父元素裡面
        that.ul.insertAdjacentHTML('beforeend', li);
        that.fsection.insertAdjacentHTML('beforeend', section);
        that.init();
        }
    

3.5刪除

  • 為元素的刪除按鈕x綁定點擊事件

     this.remove[i].onclick = this.removeTab;
    
  • 獲取到點擊的刪除按鈕的所在的父元素的所有,刪除對應的標題與內容

     removeTab(e) {
         e.stopPropagation(); // 阻止冒泡 防止觸發li 的切換點擊事件
         var index = this.parentNode.index;
         console.log(index);
         // 根據索引號刪除對應的li 和section   remove()方法可以直接刪除指定的元素
         that.lis[index].remove();
         that.sections[index].remove();
         that.init();
         // 當我們刪除的不是選中狀態的li 的時候,原來的選中狀態li保持不變
         if (document.querySelector('.liactive')) return;
         // 當我們刪除了選中狀態的這個li 的時候, 讓它的前一個li 處於選定狀態
         index--;
         // 手動調用我們的點擊事件  不需要滑鼠觸發
         that.lis[index] && that.lis[index].click();
     }
    

3.6編輯

  • 為元素(標題與內容)綁定雙擊事件

     this.spans[i].ondblclick = this.editTab;
     this.sections[i].ondblclick = this.editTab;
    
  • 在雙擊事件處理文本選中狀態,修改內部DOM節點,實現新舊value值的傳遞

    editTab() {
        var str = this.innerHTML;
        // 雙擊禁止選定文字
        window.getSelection ? window.getSelection().removeAllRanges() : 				    document.selection.empty();
        // alert(11);
          this.innerHTML = '<input type="text" />';
          var input = this.children[0];
          input.value = str;
          input.select(); // 文本框裡面的文字處於選定狀態
          // 當我們離開文本框就把文本框裡面的值給span 
          input.onblur = function() {
          this.parentNode.innerHTML = this.value;
          };
          // 按下回車也可以把文本框裡面的值給span
          input.onkeyup = function(e) {
          if (e.keyCode === 13) {
          // 手動調用表單失去焦點事件  不需要滑鼠離開操作
          this.blur();
          }
        }
    }