原型鏈模式

原型鏈模式基礎

//構造函數模式
function CreateJsPerson(name,age){
    this.name = name;
    this.age = age;
    this.writeJs = function(){
         console.log('my name is ' + this.name +'i can write js') 
    }
}
var p1 = new CreateJsPerson('zzz',20);
var p2 = new CreateJsPerson('aaa',12);
console.log(p1.writeJs === p2.writeJs)//false

構造函數模式中擁有了類和實例的概念,並且實例和實例之間是相互獨立開的–>實例識別

//原型鏈模式
function CreateJsPerson(name,age){
    this.name = name;
    this.age = age;
}
CreateJsPerson.prototype.writeJs = function (){
    console.log('my name is ' + this.name +'i can write js') 
}
var p1 = new CreateJsPerson('zzz',20);
var p2 = new CreateJsPerson('aaa',12);
console.log(p1.writeJs === p2.writeJs)//true

基於構造函數模式的原型模式解決了方法或者屬性共有的問題

把實例之間相同的屬性和方法提取成公有的屬性和方法

想讓誰公有就把它放在CreateJsPerson.prototype上

  • 每一個函數數據類型(普通函數,類),都有一個天生自帶的屬性:prototype(原型),並且這個屬性是這個對象數據類型的值
  • 並且在protype在瀏覽器上瀏覽器天生給它加一個屬性constructor(構造函數),屬性值是當前函數本身
  • 每一個對象數據類型(普通的對象,實例,prototype…)也天生自帶一個屬性:__ proto __ ,這個屬性是當前實例所屬類的原型
 function Fn(){
     this.x = 100;
 }
 Fn.prototype.getX = function(){
     console.log(this.x)
 }
 var f1 = new Fn;
 var f2 = new Fn;
 console.log(Fn.prototype.constructor === Fn);//true
 f1.hasOwnPrototype('x');//hasOwnPrototype是f1的一個屬性
 f1.getX === f2.getx //true
 f1.__proto__getX === f2.getX//true
 f1.getX === Fn.prototype.getX //true

原型鏈模式圖

Object是js中所有對象屬性類型的基類

  • f1 instanceof Object -->true 因爲f1通過__proto__可以向上級查找,不管有多少級,最後總能找到Object
  • 在Object.prototype上沒有__proto__這個屬性
  • 原型鏈模式
    1. f1.hasOwnPrototype(‘x’);//hasOwnPrototype是f1的一個屬性
    2. 但是我們發現f1的私有屬性上並沒有這個方法,那如何處理呢?
    3. 通過對象名.屬性名的方式獲取屬性值的時候,首先在對象的私有的屬性進行查找,如果在私有中存在這個屬性,則獲取的是私有的屬性值
    4. 如果私有的沒有,則通過__proto__找到所屬類的原型(類的原型上定義的屬性和方法都是當前實例的公有屬性和方法)
    5. 如果原型上也沒有,則通過原型上的__proto__繼續向上查找,一直找到Object.prototype爲止
    6. 這種查找的機制就是我們的“原型鏈模式”
 function Fn(){
     this.x = 100;
     this.sum = function(){};
 }
 Fn.prototype.getX = function(){
     console.log(this.x)
 }
 Fn.prototype.sum = function(){};
 var f1 = new Fn;
 var f2 = new Fn;
f1.sum = function(){
    //修改自己私有的sum
}
f1.__proto__.sum= function(){
    //修改所屬類原型上的sum
}
f1.prototype.sum= function(){
    //修改公有上的sum
}

原型鏈模式擴展-this和原型擴展

function Fn(){
    this.x = 100;
    this.y = 200;
    this.getY = function(){
        console.log(this.y)
    }
}
Fn.prototype = {
    constructor:Fn,
    y:300,
    getX:function(){
        console.log(this.x);
    },
    getY:function(){
        console.log(this.y);
    }
};
var f = new Fn;
f.getX();//this是f-->console.log(f.x)-->100
f.__proto__.getX();//this是f.__proto__-->console.log(f.__proto__.x) -->undefined
Fn.prototype.getX();//this是Fn.prototype -->console.log(Fn.prototype.x) -->undefined

f.getY();//this是f-->console.log(f.y)-->200
f.__proto__.getY();//this是f.__proto__-->console.log(f.__proto__.y)-->
  1. 在原型模式中,this常用的有兩種情況
  2. 在類中this.xxx=xxx ->當前類的實例
  3. 在某一個方法中的this ->看執行的時候“.”,前面是誰,this就是誰
    1. 需要先確定this的指向(this是誰)
    2. 把this替換成對應的代碼
    3. 按照原型鏈
Array.prototype.myUnique = function(){
   //this-->
}
var ary = [];
ary.myUnique();//this-->ary(常用)
Array.prototype.myUnique();//this-->Array.prototype

在內置類的原型上擴展我們的方法:去重(還有很多方式)

Array.prototype.myUnique = function(){
   //this-->ary
   var obj = {};
   for(var i=0;i<this.length;i++){
       var cur = this[i];
       if(obj[cur] == cur){
           this[i] = this[this.length - 1];
           this.length--;
           i--;
           continue;
       }
       obj[cur] = cur;
   }
   obj = null;
}
var ary = [12,13,12,13,14,15];
ary.myUnique();//this-->ary(常用)
//鏈式寫法:執行完成數組的一個方法可以緊接着執行下一個方法
//原理:ary爲什麼可以使用sort方法?因爲sort是Array.prototype上公有的方法,而數組ary是Array這個類的一個實例
//sort執行完成的返回值是一個排序後的"數組",可以繼續執行reverse
//reverse執行完成的返回值是一個數組,可以繼續執行pop
//pop執行完成之後的返回值是被刪除的那個元素,不是一個數組了,所以在執行push報錯
ary.sort(function(a,b){
    return a-b;
}).reverse().pop();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章