構造函數和原型

對象的三種創建方式

  1. 字面量方式

    var obj = {};
    
  2. new關鍵字

    var obj = new Object();
    
  3. 構造函數方式(ES6之前大量生成對象)

    function Person(name,age){
      this.name = name;
      this.age = age;
    }
    var obj = new Person('zs',12);
    

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);//實例成員只能通過實例化的對象來訪問

靜態成員

  • 靜態成員 在構造函數本身上添加的成員 如下列代碼中 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);//靜態成員只能通過構造函數來訪問

構造函數的問題

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

2.構造函數原型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();//我會唱歌

3. 對象原型

  • 對象都會有一個屬性 proto 指向構造函數的 prototype 原型對象
  • 實例對象的 __proto__和構造函數的 prototype 是等價的
  • 先找構造函數有沒有方法,沒有再去prototype找。

4.constructor構造函數

  • 對象原型( proto)和構造函數(prototype)原型對象裏面都有一個屬性 constructor 屬性 ,constructor 我們稱爲構造函數,因爲它指回構造函數本身。
  • 如果我們修改了原來的原型對象,給原型對象賦值的是一個對象(原對象star被覆蓋),則必須手動的利用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)

5.原型鏈和成員的查找機制

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

6.原型對象中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

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

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

8.繼承——call()

  • 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,

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

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

10. 借用原型對象繼承方法

  1. 先定義一個父構造函數
  2. 再定義一個子構造函數
  3. 子構造函數繼承父構造函數的屬性(使用call方法)

方法

  1. 子類構造函數的原型對象指向父類實列對象。
  2. 因爲父類實例對象指向父類的prototype,這樣就形成子類prototype——>父類實例——>父類構造函數prototype。
// 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);

11.ES5新增方法

數組方法forEach遍歷數組

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

數組方法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] //返回值是一個新數組

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

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

獲取對象的屬性名

  • Object.keys(對象) 獲取到當前對象中的屬性名 ,返回值是一個數組
 var obj = {
     id: 1,
     pname: '小米',
     price: 1999,
     num: 2000
};
var result = Object.keys(obj)
console.log(result)//[id,pname,price,num]

object.defineProperty

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

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