關於原型的一些理解,儘可能寫的詳細一點。

 學了前端一段時間了,對js當時花了不少時間可是隨着後面學習框架有些就忘了。如今重新開始記錄下重要的知識點。有不少知識也是查閱js高程和別人的博客,所用的一些例子也是引用那些以爲頗有表明意義的,在文章最後貼出有關的博客。有錯的地方也請你們指出。有些知識深究的話我能力有限,也不知道;因此不少做爲一個結論記住就行。javascript

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

 var a={"name":"hello"}; 這是一個普通的對象。 function f1(){};    var f2 = function(){}; 這是函數對象。那麼函數對象和對象又有什麼不一樣了。函數有個叫原型的東西是個對象,可是對象沒有。這裏引入了 prototype 這個屬性,那麼這個就是原型對象了,固然不是。它是個指針指向原型對象。這裏要記住prototype是個指針後面雖然還有繼承有關可是先記住是個指針。這裏就先說到這裏,區別函數對象和對象,以及一個重要屬性prototype,對象沒這個屬性。java

2,那麼對象和函數對象又有什麼聯繫了,首先建立一個普通的對象var person = {}或者var 0=new object()。這是個普通的對象,經過這種字面量能夠創造不少單個對象。可是會產生大量重複代碼,因此有了工廠模式的出現。web

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對象,能夠屢次調用這個函數。可是卻沒有解決對象的識別問題(不知道這個對象的類型)。因此以後重頭戲來了,有了構造函數,這個知識點就涉及原型了。app

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指向新對象);this

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

4'返回新的對象。 

new Animal("cat") = { var obj = {}; obj.__proto__ = Animal.prototype; var result = Animal.call(obj,"cat");
//var result = obj.Animal("cat")。至關於Animal在obj做用域裏面運行
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__

....................................................................................................................................................................................................................................................................

如今還有個constructor。,constructor始終指向建立當前對象的構造函數。

function Person(name,age){ this.name = name; this.age = age; } Person.prototype = { getName:function(){ return this.name; }, getAge:function(){ return this.age; } } var p = new Person("Nicholas",18); console.log(p.constructor); //Object()

這裏p.constructor不等於person是由於上面的給她至關於從new成一個新的對象

Person.prototype = new Object({
  getName:function(){
    return this.name;
  },
因此結果是boject。而後如今對new constructor prototype __proto__有了認識以後來講說原型鏈。首先是構造函數的原型鏈。

  構造函數也是有 __proto__屬性的,而後也會造成一個原型鏈。

Constructor ----> Function.prototype ----> Object.prototype ----> null  

 

1,Constructor 的 __proto__ 是 Function.prototype
2,Function.prototype 的 __proto__ 是 Object.prototype
3,Object.prototype 的 __proto__ 是 nullda
答:這個了也只能這麼理解,一個函數因爲是Function類型,因此它的__proto__是Function.prototype,而Function自己也是個函數(能夠new Function嘛),因此Function的__proto__也是Function.prototype。然而而後Function.prototype天然是一個對象,因此Function.prototype的__proto__是Object.prototype。最後指向js的萬惡之源null。爲何說是萬惡之源了,由於才學js就據說萬物皆繼承於null。
 
而後構造函數的實例又是怎麼造成的原型鏈了,

function f()={};

var obj=new f();

這是一個普通實例的原型的原型鏈。

 

 還有不少沒搞懂的,這部份內容確實多先到這吧,之後在慢慢更新。

相關文章
相關標籤/搜索