構造函數和原型,繼承,es5新增方法

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();

  2. 示例

    // 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 {
    }

  2. 示例

    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
      

      以上代碼運行結果爲:

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

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

1.構造函數和原型

1.1對象的三種創建方式–複習

  1. 字面量方式
    var obj = {};
  2. new關鍵字
    var obj = new Object();
  3. 構造函數方式
    function Person(name,age){
    this.name = name;
    this.age = age;
    }
    var obj = new Person(‘zs’,12);

1.2靜態成員和實例成員

1.2.1實例成員

實例成員就是構造函數內部通過this添加的成員 如下列代碼中uname age sing 就是實例成員,實例成員只能通過實例化的對象來訪問

 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
     this.sing = function() {
     console.log('我會唱歌');
    }
}
var ldh = new Star('劉德華', 18);
console.log(ldh.uname);//實例成員只能通過實例化的對象來訪問

1.2.2靜態成員

靜態成員 在構造函數本身上添加的成員 如下列代碼中 sex 就是靜態成員,靜態成員只能通過構造函數來訪問

 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
     this.sing = function() {
     console.log('我會唱歌');
    }
}
Star.sex = '男';
var ldh = new Star('劉德華', 18);
console.log(Star.sex);//靜態成員只能通過構造函數來訪問

1.3構造函數的問題

構造函數方法很好用,但是存在浪費內存的問題。

在這裏插入圖片描述

1.4構造函數原型prototype

構造函數通過原型分配的函數是所有對象所共享的。

JavaScript 規定,每一個構造函數都有一個prototype 屬性,指向另一個對象。注意這個prototype就是一個對象,這個對象的所有屬性和方法,都會被構造函數所擁有。

我們可以把那些不變的方法,直接定義在 prototype 對象上,這樣所有對象的實例就可以共享這些方法。

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
Star.prototype.sing = function() {
	console.log('我會唱歌');
}
var ldh = new Star('劉德華', 18);
var zxy = new Star('張學友', 19);
ldh.sing();//我會唱歌
zxy.sing();//我會唱歌

在這裏插入圖片描述

1.5對象原型

對象都會有一個屬性 __proto__ 指向構造函數的 prototype 原型對象,之所以我們對象可以使用構造函數 prototype 原型對象的屬性和方法,就是因爲對象有 __proto__ 原型的存在。
__proto__對象原型和原型對象 prototype 是等價的
__proto__對象原型的意義就在於爲對象的查找機制提供一個方向,或者說一條路線,但是它是一個非標準屬性,因此實際開發中,不可以使用這個屬性,它只是內部指向原型對象 prototype

在這裏插入圖片描述
在這裏插入圖片描述
1.6constructor構造函數

對象原型( __proto__)和構造函數(prototype)原型對象裏面都有一個屬性 constructor 屬性 ,constructor 我們稱爲構造函數,因爲它指回構造函數本身。
constructor 主要用於記錄該對象引用於哪個構造函數,它可以讓原型對象重新指向原來的構造函數。
一般情況下,對象的方法都在構造函數的原型對象中設置。如果有多個對象的方法,我們可以給原型對象採取對象形式賦值,但是這樣就會覆蓋構造函數原型對象原來的內容,這樣修改後的原型對象 constructor  就不再指向當前構造函數了。此時,我們可以在修改後的原型對象中,添加一個 constructor 指向原來的構造函數。

如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用constructor指回原來的構造函數如:

 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
 }
 // 很多情況下,我們需要手動的利用constructor 這個屬性指回 原來的構造函數
 Star.prototype = {
 // 如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用constructor指回原來的構造函數
   constructor: Star, // 手動設置指回原來的構造函數
   sing: function() {
     console.log('我會唱歌');
   },
   movie: function() {
     console.log('我會演電影');
   }
}
var zxy = new Star('張學友', 19);
console.log(zxy)

以上代碼運行結果,設置constructor屬性如圖:
在這裏插入圖片描述
如果未設置constructor屬性,如圖:

在這裏插入圖片描述

1.7原型鏈

每一個實例對象又有一個proto屬性,指向的構造函數的原型對象,構造函數的原型對象也是一個對象,也有proto屬性,這樣一層一層往上找就形成了原型鏈。

在這裏插入圖片描述

1.8構造函數實例和原型對象三角關係

1.構造函數的prototype屬性指向了構造函數原型對象
2.實例對象是由構造函數創建的,實例對象的__proto__屬性指向了構造函數的原型對象
3.構造函數的原型對象的constructor屬性指向了構造函數,實例對象的原型的constructor屬性也指向了構造函數

在這裏插入圖片描述

1.9原型鏈和成員的查找機制

任何對象都有原型對象,也就是prototype屬性,任何原型對象也是一個對象,該對象就有proto屬性,這樣一層一層往上找,就形成了一條鏈,我們稱此爲原型鏈;

當訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性。
如果沒有就查找它的原型(也就是 __proto__指向的 prototype 原型對象)。
如果還沒有就查找原型對象的原型(Object的原型對象)。
依此類推一直找到 Object 爲止(null)。
__proto__對象原型的意義就在於爲對象成員查找機制提供一個方向,或者說一條路線。

1.10原型對象中this指向

構造函數中的this和原型對象的this,都指向我們new出來的實例對象

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
var that;
Star.prototype.sing = function() {
    console.log('我會唱歌');
    that = this;
}
var ldh = new Star('劉德華', 18);
// 1. 在構造函數中,裏面this指向的是對象實例 ldh
console.log(that === ldh);//true
// 2.原型對象函數裏面的this 指向的是 實例對象 ldh

在這裏插入圖片描述

1.11通過原型爲數組擴展內置方法

 Array.prototype.sum = function() {
   var sum = 0;
   for (var i = 0; i < this.length; i++) {
   sum += this[i];
   }
   return sum;
 };
 //此時數組對象中已經存在sum()方法了  可以始終 數組.sum()進行數據的求

2.繼承

2.1call()

  • call()可以調用函數

  • call()可以修改this的指向,使用call()的時候 參數一是修改後的this指向,參數2,參數3…使用逗號隔開連接

    function fn(x, y) {
    console.log(this);
    console.log(x + y);
    }
    var o = {
    name: ‘andy’
    };
    fn.call(o, 1, 2);//調用了函數此時的this指向了對象o,

在這裏插入圖片描述

2.2子構造函數繼承父構造函數中的屬性

  1. 先定義一個父構造函數

  2. 再定義一個子構造函數

  3. 子構造函數繼承父構造函數的屬性(使用call方法)

    // 1. 父構造函數
    function Father(uname, age) {
    // this 指向父構造函數的對象實例
    this.uname = uname;
    this.age = age;
    }
    // 2 .子構造函數
    function Son(uname, age, score) {
    // this 指向子構造函數的對象實例
    3.使用call方式實現子繼承父的屬性
    Father.call(this, uname, age);
    this.score = score;
    }
    var son = new Son(‘劉德華’, 18, 100);
    console.log(son);

在這裏插入圖片描述
2.3借用原型對象繼承方法

  1. 先定義一個父構造函數

  2. 再定義一個子構造函數

  3. 子構造函數繼承父構造函數的屬性(使用call方法)

    // 1. 父構造函數
    function Father(uname, age) {
    // this 指向父構造函數的對象實例
    this.uname = uname;
    this.age = age;
    }
    Father.prototype.money = function() {
    console.log(100000);
    };
    // 2 .子構造函數
    function Son(uname, age, score) {
    // this 指向子構造函數的對象實例
    Father.call(this, uname, age);
    this.score = score;
    }
    // Son.prototype = Father.prototype; 這樣直接賦值會有問題,如果修改了子原型對象,父原型對象也會跟着一起變化
    Son.prototype = new Father();
    // 如果利用對象的形式修改了原型對象,別忘了利用constructor 指回原來的構造函數
    Son.prototype.constructor = Son;
    // 這個是子構造函數專門的方法
    Son.prototype.exam = function() {
    console.log(‘孩子要考試’);

    }
    var son = new Son(‘劉德華’, 18, 100);
    console.log(son);

如上代碼結果如圖:
在這裏插入圖片描述

3.ES5新增方法

3.1數組方法forEach遍歷數組

 arr.forEach(function(value, index, array) {
       //參數一是:數組元素
       //參數二是:數組元素的索引
       //參數三是:當前的數組
 })
  //相當於數組遍歷的 for循環 沒有返回值

3.2數組方法filter過濾數組

  var arr = [12, 66, 4, 88, 3, 7];
  var newArr = arr.filter(function(value, index,array) {
  	 //參數一是:數組元素
     //參數二是:數組元素的索引
     //參數三是:當前的數組
     return value >= 20;
  });
  console.log(newArr);//[66,88] //返回值是一個新數組

3.3數組方法some

some 查找數組中是否有滿足條件的元素 
 var arr = [10, 30, 4];
 var flag = arr.some(function(value,index,array) {
    //參數一是:數組元素
     //參數二是:數組元素的索引
     //參數三是:當前的數組
     return value < 3;
  });
console.log(flag);//false返回值是布爾值,只要查找到滿足條件的一個元素就立馬終止循環

3.4篩選商品案例

  1. 定義數組對象數據
    var data = [{
    id: 1,
    pname: ‘小米’,
    price: 3999
    }, {
    id: 2,
    pname: ‘oppo’,
    price: 999
    }, {
    id: 3,
    pname: ‘榮耀’,
    price: 1299
    }, {
    id: 4,
    pname: ‘華爲’,
    price: 1999
    }, ];
  2. 使用forEach遍歷數據並渲染到頁面中
    data.forEach(function(value) {
    var tr = document.createElement(‘tr’);
    tr.innerHTML = ‘’ + value.id + ‘’ + value.pname + ‘’ + value.price + ‘’;
    tbody.appendChild(tr);
    });
  3. 根據價格篩選數據
    1. 獲取到搜索按鈕併爲其綁定點擊事件
      search_price.addEventListener(‘click’, function() {
      });
    2. 使用filter將用戶輸入的價格信息篩選出來
      search_price.addEventListener(‘click’, function() {
      var newDate = data.filter(function(value) {
      //start.value是開始區間
      //end.value是結束的區間
      return value.price >= start.value && value.price <= end.value;
      });
      console.log(newDate);
      });
    3. 將篩選出來的數據重新渲染到表格中
      1. 將渲染數據的邏輯封裝到一個函數中
        function setDate(mydata) {
        // 先清空原來tbody 裏面的數據
        tbody.innerHTML = ‘’;
        mydata.forEach(function(value) {
        var tr = document.createElement(‘tr’);
        tr.innerHTML = ‘’ + value.id + ‘’ + value.pname + ‘’ + value.price + ‘’;
        tbody.appendChild(tr);
        });
        }
      2. 將篩選之後的數據重新渲染
        search_price.addEventListener(‘click’, function() {
        var newDate = data.filter(function(value) {
        return value.price >= start.value && value.price <= end.value;
        });
        console.log(newDate);
        // 把篩選完之後的對象渲染到頁面中
        setDate(newDate);
        });
    4. 根據商品名稱篩選
      1. 獲取用戶輸入的商品名稱
      2. 爲查詢按鈕綁定點擊事件,將輸入的商品名稱與這個數據進行篩選
        search_pro.addEventListener(‘click’, function() {
        var arr = [];
        data.some(function(value) {
        if (value.pname === product.value) {
        // console.log(value);
        arr.push(value);
        return true; // return 後面必須寫true
        }
        });
        // 把拿到的數據渲染到頁面中
        setDate(arr);
        })

3.5some和forEach區別

  • 如果查詢數組中唯一的元素, 用some方法更合適,在some 裏面 遇到 return true 就是終止遍歷 迭代效率更高
  • 在forEach 裏面 return 不會終止迭代

3.6trim方法去除字符串兩端的空格

var str = '   hello   '
console.log(str.trim())  //hello 去除兩端空格
var str1 = '   he l l o   '
console.log(str.trim())  //he l l o  去除兩端空格

3.7獲取對象的屬性名

Object.keys(對象) 獲取到當前對象中的屬性名 ,返回值是一個數組

 var obj = {
     id: 1,
     pname: '小米',
     price: 1999,
     num: 2000
};
var result = Object.keys(obj)
console.log(result)//[id,pname,price,num]

3.8Object.defineProperty

Object.defineProperty設置或修改對象中的屬性

Object.defineProperty(對象,修改或新增的屬性名,{
		value:修改或新增的屬性的值,
		writable:true/false,//如果值爲false 不允許修改這個屬性值
		enumerable: false,//enumerable 如果值爲false 則不允許遍歷
        configurable: false  //configurable 如果爲false 則不允許刪除這個屬性 屬性是否可以被刪除或是否可以再次修改特性
})	
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章