作為一個致力於前端開發的人員,能夠熟練掌握javascript的原理和機制是每個小白的必經之路,這也是最痛苦的。有人說前端功力好不好最主要的就是看對js的掌握能力,有人說十年也啃不完一門javascript。而我們能夠知道的是:javascript是每個前端學習的核心技能(想想之後的node.js、 ...
作為一個致力於前端開發的人員,能夠熟練掌握javascript的原理和機制是每個小白的必經之路,這也是最痛苦的。有人說前端功力好不好最主要的就是看對js的掌握能力,有人說十年也啃不完一門javascript。而我們能夠知道的是:javascript是每個前端學習的核心技能(想想之後的node.js、vue.js,顫抖吧!!!)
本期主要介紹一下js當中的prototype原型(emmm,不知道你們覺得難不難,反正我當時看了許多博客都一知半解,也許現在也是,所以不足之處,請留言指教。。)
先瞭解一下prototype是什麼
function Person() {//首先隨便定義一個函數 }
在控制台看看這個函數的prototype有什麼
我們發現裡面有兩個東西:constructor 和 __protot__,並且constructor指向Person這個函數,而__prototype__展開後有許多方法,並且也存在一個constructor
(這裡的展開我就不貼圖了,大家要自己動手才能對知識有更深刻的體會,千萬不要做伸手黨,只會坑自己的,這點我是深有體會)
這時候我們會發現,每個函數都有一個prototype屬性,prototype包含函數實例共用的方法和屬性。
接下來我們繼續,通過Person函數創建兩個實例對象
function Person() { } Person.prototype.name = "person"//在Person的原型上添加一個name屬性 var person1 = new Person() var person2 = new Person()
我們發現兩個實例化對象中都繼承到了name這個屬性,所以說當通過new來生成一個類的對象時,prototype對象的屬性就會成為實例化對象的屬性。
現在我們大概知道了,在js中,你創建的每一個函數中都會產生一個prototype,這個函數以及它的實例化對象都可以用到prototype中的共用方法。我們也發現除了js本身給出的prototype的方法外,我們也可以在prototype中添加自定義方法。
我們再看一個很有意思的東西
看看我們發現了什麼新大陸哈哈哈,原來我們之前用的數組方法都是從Array原型中來的,正因為js將這些方法寫在Array.prototype中,所以我們才能在定義的數組中使用它。
(你不相信??那你可以自己動手試試。)
Array.prototype.hahaha ="balabal" //在Array.prototype中添加一個新屬性hahaha var arr = []; var arr1 = new Array; //在控制臺中輸入arr.hahaha 或 arr1.hahaha ,你看看結果是不是“balabal”
現在知道為什麼說prototype是js中的一個重要機制了吧
之前我說自己覺得原型很難,就是因為對prototype和__proto__混淆不清
看圖我們可以發現,在Person prototype中存在constructor並且指向其構造函數,而person1 和person2的__proto__都指向其實例化的構造函數Person的原型
用等式可以如此表示
Person.prototype == person1.__proto__ //true
Person.prototype.constructor === Person // true
function Person(){ this.name ="person" } var person1 = new Person; console.log(person1.name) person1.name="person1" console.log(person1.name)
// person person1
在js查找對象內的屬性時,都會遵從一個方法。JS引擎先尋找對象本身的屬性,找到就輸出,如果找不到,就到它的原型去找,如果還是找不到,就繼續往原型的原型去找。如果直到最頂層的Object.prototype,若
還是找不到,就會返回undefined
。
例如上圖,第一次輸出時由於namez屬性只在person1的原型Person.prototype中,所以輸出Person函數中的name值,之後在person1中添加name屬性,所以直接輸出person1中的name值
prototype機制的優點
function Person() { this.name = "person" this.say = function () { console.log("say prototype win") } } var person1 = new Person;
prototype的作用可以理解為產生一個共用的屬性和方法,有點類似繼承的意味。
如圖,如果我們定義一個構造函數Person,並且實例化一個函數person1,這樣我們發現,在創建person1的時候,naem屬性和say方法就已經產生在person1函數中了,那如果我們創建大量的實例,那不是每個實例都會先將構造函數的屬性和方法加入進來,這種共用方式是不是感覺有點low呢?(而且還浪費系統資源)現在瞭解了prototype,如果我們將這些屬性和方法寫在Person函數的原型上,那麼它的實例化函數需要使用這些方法的時候直接找到原型上即可,這樣就真正實現了共用。(大家可以自己動手把共用方法寫在Person.prototype中試試呢!!)
優點:屬性和方法定義在原型上,那麼所有實例對象就能共用,不僅節省了記憶體,還體現了實例對象之間的聯繫。
關於原型差不多就是這些,以後有新的看法也會繼續更新的,如果以上哪裡有不對的地方,請務必要告訴我,謝謝!