1. 程式人生 > >關於原型的一些理解,盡量寫的詳細一點。

關於原型的一些理解,盡量寫的詳細一點。

部分 解釋 也會 發生 console 什麽是對象 func style 例子

學了前端一段時間了,對js當時花了很多時間但是隨著後面學習框架有些就忘了。現在從新開始記錄下重要的知識點。有很多知識也是查閱js高程和別人的博客,所用的一些例子也是引用那些覺得很有代表意義的,在文章最後貼出有關的博客。有錯的地方也請大家指出。有些知識深究的話我能力有限,也不知道;所以很多作為一個結論記住就行。

1.首先什麽是對象,什麽是函數對象。有些地方也叫函數,我查了下函數和函數對象應該是指代的同一個東西,沒有區別。首先

var a={"name":"hello"}; 這是一個普通的對象。 function f1(){}; var f2 = function(){}; 這是函數對象。那麽函數對象和對象又有什麽不同了。函數有個叫原型的東西是個對象,但是對象沒有。這裏引入了 prototype

這個屬性,那麽這個就是原型對象了,當然不是。它是個指針指向原型對象。這裏要記住prototype是個指針後面雖然還有繼承有關但是先記住是個指針。這裏就先說到這裏,區別函數對象和對象,以及一個重要屬性prototype,對象沒這個屬性。

2,那麽對象和函數對象又有什麽聯系了,首先創建一個普通的對象var person = {}或者var 0=new object()。這是個普通的對象,通過這種字面量可以創造很多單個對象。但是會產生大量重復代碼,所以有了工廠模式的出現。

function creatPerson (name, age) {
    var person = new Object(); 
    person.name 
= name; person.age = age; person.sayName = function () { alert(this.name); }; return person;
}

var person1= creatPerson ("tom",29)
 

他能創建一個包含一些信息的person對象,可以多次調用這個函數。但是卻沒有解決對象的識別問題(不知道這個對象的類型)。所以之後重頭戲來了,有了構造函數,這個知識點就涉及原型了。

function CreatePerson(name, age, say){
    this.name = name;
    
this.age = age; this.say = say; this.should = function(){ console(this.say); } } var person1 = new CreatePerson("","","");

這個函數也很簡單,但是和之前的工廠模式有了些區別。這個函數有個很重要的 new 操作符。看一個實例:

function Animal(name){
           this.name = name;
         }
    Animal.color = "black";
    Animal.prototype.say = function(){
            console.log("I‘m " + this.name);
         };
    var cat = new Animal("cat");

    console.log(
            cat.color, //undefine
            cat.name  //cat
 );
    cat.say(); //I‘m cat

     console.log(
            Animal.name, //Animal
            Animal.color //back
   );
    Animal.say(); //Animal.say is not a function

這個函數沒看答案之前有可能你是不太清楚,但是看了答案你是應該是能得出一些結論的。雖然你可能不知道發生了什麽。首先 console.log( Animal.name, //Animal Animal.color //back ); 這個比較簡單沒什麽說的,不懂的函數的name屬性可以看下。 cat.color, //undefine 這個是重點,這裏看的出來構造出來的實例並沒有繼承到color這個屬性,那麽就要引入構造函數的工作的模式了。關鍵的new字符,js高程是這麽解釋的:

1‘創建一個新的對象;

2‘將構造函數作用域賦給新的對象(即this指向新對象);

3‘執行構造函數裏面的代碼;

4‘返回新的對象。

new Animal("cat") = {

    var obj = {};

    obj.__proto__ = Animal.prototype;

    var result = Animal.call(obj,"cat");

    return typeof result === ‘object‘? result : obj;
}

這是一個模仿new運行機制的偽代碼,這裏我們看到一個新的東西出現了 __proto__ ,先給這個過程看完:obj的__proto__ 指向Animal的原型對象prototype然後你大概懂了

cat.say(); //I‘m cat 之後,在obj對象的執行環境調用Animal函數並傳遞參數“cat”。 相當於var result = obj.Animal("cat")。 當這句執行完之後,obj便產生了屬性name並賦值為"cat"。可能第二個你看的不太明白那你就可以看看call屬性,以及this了。這裏先不提,後面可以在仔細做下筆記。引入了__proto__ 那麽就相當於引入了原型鏈了,當你實例化一個對象,就會形成一個原型鏈,他會去找構造函數的prototype,然後逐級向上尋找,其實原型的重點是__proto__ ,我這裏將引入一兩道例題幫助自己記憶,以及自己的理解。

  var animal = function(){};
    var dog = function(){};
    animal.price = 2000;
    dog.prototype = animal;
    var tidy = new dog();  //tidy.constructor=dog;實例tidy可以通過授權找到它並用以檢測自己的構造函數
    console.log(dog.price);   //undefined
    console.log(tidy.price);   // 2000

1‘首先 dog.prototype = animal;這裏沒有問題的, 我們可以賦值任何類型的對象到原型上,但是不能賦值原子類型的值, 比如如下代碼是無效的: Foo.prototype = 1;

2‘將 animal的值賦給dog的原型對象。 console.log(dog.price);針對這句代碼。首先是dog自己的本身的函數是沒price這個屬性的,然後原型上有,但是兩者是沒有關系的。

3’ 它先通過查找自生,然後再循著__proto__去原型鏈中尋找,全局中也沒有,都沒有所以讀取不到price這個屬性。

var Animal = function(){}; Animal.prototype.say = function(){ alert("a"); }; Animal.say() //Animal.say s not a function

這個簡短的例子也是能說明問題的,然後在來看下面這個例子:

  var animal = function(){};
    var dog = function(){};

    animal.price = 2000;
    dog.__proto__ = animal;
    var tidy = new dog();

    console.log(dog.price) //2000
    console.log(tidy.price) // undefined
1. dog.__proto__ = animal;直接找到 animal,獲取值dog.price==2000;
2. tidy.__proto__= dog.prototype;
3.
tidy.__proto__.__proto__ === dog.prototype.__proto__=== Object.prototype;通過這個原型鏈確實找不到。這裏要區別prototype和__proto__

今天寫的很淺,還有很多問題都沒有涉及,睡了還是寫了很久。明天繼續寫原型這部分的,然後遇到的this,call這些也會寫,慢慢來每天寫點。

關於原型的一些理解,盡量寫的詳細一點。