JavaScript Prototype

定義和用法

prototype 屬性使您有能力向對象添加屬性和方法。javascript

實例

在本例中,將展現如何使用 prototype 屬性來向對象添加屬性:html

<script type="text/javascript">

function employee(name,job,born)
{
this.name=name;
this.job=job;
this.born=born;
}

var bill=new employee("Bill Gates","Engineer",1985);

employee.prototype.salary=null;
bill.salary=20000;

document.write(bill.salary);

</script>

輸出:java

20000

一般來講,javascript中的對象就是一個指向prototype的指針和一個自身的屬性列表。javascript建立對象時採用了寫時複製的理念。app

只有構造器才具備prototype屬性,原型鏈繼承就是建立一個新的指針,指向構造器的prototype屬性。函數

prototype屬性之因此特別,是由於javascript時讀取屬性時的遍歷機制決定的。本質上它就是一個普通的指針。this

構造器包括:spa

1.Object
2.Function
3.Array
4.Date
5.String

下面咱們來舉一些例子吧prototype

//每一個function都有一個默認的屬性prototype,而這個prototype的constructor默認指向這個函數
//注意Person.constructor 不等於 Person.prototype.constructor. Function實例自帶constructor屬性
   function Person(name) { 
        this.name = name; 
    }; 
    Person.prototype.getName = function() { 
        return this.name; 
    }; 
    var p = new Person("ZhangSan"); 
   
    console.log(Person.prototype.constructor === Person); // true 
    console.log(p.constructor === Person);  // true ,這是由於p自己不包含constructor屬性,因此這裏其實調用的是Person.prototype.constructor

咱們的目的是要表示指針

1.代表Person繼承自Animalcode

2. 代表p2是Person的實例

咱們修改一下prototype屬性的指向,讓Person能獲取Animal中的prototype屬性中的方法。也就是Person繼承自Animal(人是野獸) 

function Person(name) { 
        this.name = name; 
    }; 
    Person.prototype.getName = function() { 
        return this.name; 
    }; 
    var p1 = new Person("ZhangSan"); 
    
    console.log(p.constructor === Person);  // true 
    console.log(Person.prototype.constructor === Person); // true 

     function Animal(){ }
    
     Person.prototype = new Animal();//之因此不採用Person.prototype  = Animal.prototype,是由於new 還有其餘功能,最後總結。
     var p2 = new Person("ZhangSan");
    
//(p2 -> Person.prototype -> Animal.prototype, 因此p2.constructor其實就是Animal.prototype.constructor)
     
     console.log(p2.constructor === Person);  // 輸出爲false ,但咱們的本意是要這裏爲true的,代表p2是Person的實例。此時目的1達到了,目的2沒達到。

但若是咱們這麼修正

Person.prototype = new Animal();
Person.prototype.constructor = Person;

這時p2.consturctor是對了,指向的是Person,表示p2是Person類的實例,可是新問題出現了。此時目的2達到了,目的1沒達到。

目的1和目的2此時互相矛盾,是由於此時prototype表達了矛盾的兩個意思,

1表示父類是誰

2做爲本身實例的原型來複制

所以咱們不能直接使用prototype屬性來表示父類是誰,而是用getPrototypeOf()方法來知道父類是誰。

Person.prototype = new Animal();
     
    Person.prototype.constructor = Person;
     
    var p2 = new Person("ZhangSan");
     
    p2.constructor     //顯示 function Person() {}
     
    Object.getPrototypeOf(Person.prototype).constructor     //顯示 function Animal() {}

就把這兩個概念給分開了 ,其實經過使用 hasOwnProperty()方法,何時訪問的是實例屬性,何時訪問的是原型屬性就一清二楚了。

 

 

new作了哪些事情?

當代碼var p = new Person()執行時,new 作了以下幾件事情:

建立一個空白對象

建立一個指向Person.prototype的指針

將這個對象經過this關鍵字傳遞到構造函數中並執行構造函數。
 

具體點來講,在下面這段代碼中,

Person.prototype.getName = function() {

  }

若是咱們經過

var person = new Person();

其實相似於

var person = new Object();

person.getName = Person.prototype.getName;

所以經過person.getName()調用方法時,this指向的是這個新建立的對象,而不是prototype對象。

 

這其實在給現有函數加上新功能的狀況下會用到,咱們能夠這麼擴展示有的方法:

//function myFunc 的寫法基本上等於 var myFunc = new Function();

function myFunc () {
}

myFunc = function(func){
  //能夠在這裏作點其餘事情
    return function(){
     //能夠在這裏作點其餘事情
        return func.apply(this,arguments);
    }
}(myFunc)

也能夠在Function.prototype方法裏直接經過this來訪問上面代碼的myFunc所指向的對象

function myFunc () {
}

if (!Function.prototype.extend) {
    Function.prototype.extend = function(){
        var func = this;

        return function(){
            func.apply(this,arguments);
        }
    }
};

var myFunc = myFunc.extend();

最後總結一下:

若是採用Person.prototype  = Animal.prototype來表示Person繼承自Animal, instanceof方法也一樣會顯示p也是Animal的實例,返回爲true.

之因此不採用此方法,是由於下面兩個緣由:

1.new 建立了一個新對象,這樣就避免了設置Person.prototype.constructor = Person 的時候也會致使Animal.prototype.constructor的值變爲Person,而是動態給這個新建立的對象一個constructor實例屬性。這樣實例上的屬性constructor就覆蓋了Animal.prototype.constructor,這樣Person.prototype.constructor和Animal.prototype.contructor就分開了。

2.Animal自身的this對象的屬性沒辦法傳遞給Person

 

可是像下面這樣直接調用構造函數又可能失敗,或者產生其餘影響。

Person.prototype = new Animal();

爲了不這種狀況,因此咱們引入了一箇中間函數。因此正確的作法應該是

Person.prototype = (funtion(){

  function F(){};

  F.prototype = Animal.prototype

  return new F();

})()
相關文章
相關標籤/搜索