prototype詳解,prototype表
原型鏈的理解是javascript中的老大難題,對于初學者非常不友好,甚至對于很多工作兩三年的程序員來說,也沒能真正理解javascript中的原型鏈的精妙設計!
我們想要理解原型鏈,首先我們先要跳出原型鏈的直接講解。
因為javascript中的原型鏈其實涉及到一個javascript的本源設計
,prototype表,就是我們先要探討一下為什么javascript要設計原型鏈,并且javacript這門語言其實是沒有原型鏈也能完美執行并且保持圖靈完備的。
首先我們看一下一個風靡世界的游戲 英雄聯盟LOL 的英雄制作過程我們用javascrip描述 以下 英雄薇恩(vn)。
function fun(){ this.val = "";} fun();那么這里的this 指的就是fun這個方法對象的prototype 通俗來講就是方法對象 如果是給你個Html的Button注冊的時間方法,那么只想的是這個button.所以this所指向的對象其實是可以。
此時我們用javascript中的對象來模擬英雄聯盟中的英雄的功能和屬性。
在原型鏈的頂端,即Object.prototype上存在一個toString方法,它返回 "[object type ]",其中 type 是對象的類型,因此可以用他來判斷對象的類型。我們使用Object.prototype.toString.call()來判定。那么為什么不直接用obj。
var hero = { heroName:&39;,heroLife:&39;, Q(){//閃避突襲復雜處理函數省略 console.log代替過程console.log(&39;)}, W(){//圣銀弩箭 復雜處理函數省略 console.log代替過程console.log(&39;)}, E(){//惡魔審判 復雜處理函數省略 console.log代替過程console.log(&39;)}, R(){//決戰時刻 復雜處理函數省略 console.log代替過程console.log(&39;)}}
好, 以上是一個英雄的對象定義, 英雄聯盟中有一個模式叫做 :克隆模式
游戲玩法界面是這樣的, 以下是十個英雄薇恩
十個一樣的英雄同場作戰,甚至私服 mod 可以容納更多的英雄,我們用代碼來描述一下!
在JavaScript中萬物都是對象,對象和對象之間也有關系,并不是孤立存在的。對象之間的繼承關系,在JavaScript中是通過prototype對象指向父類對象,直到指向Object對象為止,這樣就形成了一個原型指向的鏈條,專業術語稱之為原型鏈 。
var heros = []var herofor (var i = 0; i<10; i++) {var heroVn = {heroName:&39;,heroLife:&39;, Q(){//閃避突襲復雜處理函數省略 console.log代替過程console.log(&39;)}, W(){//圣銀弩箭 復雜處理函數省略 console.log代替過程console.log(&39;)}, E(){//惡魔審判 復雜處理函數省略 console.log代替過程console.log(&39;)}, R(){//決戰時刻 復雜處理函數省略 console.log代替過程console.log(&39;)}}heros.push(heroVn)}//制造出了十個英雄vnconsole.log(heros)
這樣設計其實是沒問題的,英雄的技能組成,以及思路都是沒問題,但是這樣設計游戲人物有j幾個重大的缺陷!!!!
這種代碼存在一個巨大的缺陷不利于商業化,可以觀察到這十個英雄唯一在游戲中不同的只是 heroLife(玩家受到的傷害不用生命值顯示不同,會根據玩家受到的傷害不同而減少, 每個玩家的生命值在游戲中都是動態變化的。
heroName(英雄名字) 以及英雄的四個技能 Q W E R 十個英雄, 都是一樣的。沒必要重復創造十次,去占據內存, 白白消耗用戶的機器性能。
我們將代碼進行改進
/共有屬性var vn = function(){}vn.prototype = {heroName:&39;, Q(){//閃避突襲復雜處理函數省略 console.log代替過程console.log(&39;)}, W(){//圣銀弩箭 復雜處理函數省略 console.log代替過程console.log(&39;)}, E(){//惡魔審判 復雜處理函數省略 console.log代替過程console.log(&39;)}, R(){//決戰時刻 復雜處理函數省略 console.log代替過程console.log(&39;)}}var heros = []var vn1 for (var i = 0; i<10; i++) {vn1 = {heroLife:&39;}vn1.__proto__ = vn.prototype}
好了,通過以上的改進,我們就達到我們的目的,英雄的生命值屬于,每一個唯一id的英雄,但是英雄的共有屬性不在占據獨有的內存空間 而是去指向共有的英雄屬性不在白白浪費內存空間了!這也是原型鏈設計的最終目的以及初衷!
但是這樣的寫法,很拗口也很難理解,JS的官方組織也有意去弱化這個設計,讓不知道這個設計的程序員也可以很好的使用這個功能去節約內存,然后就有了new 操作符!
new操作符實際上只做了四步
新生成一個對象
鏈接到原型
JavaScript中我們在定義構造函數的時候就會默認有一個prototype的屬性。每個對象實例化后其實就是拷貝構造函數中除開prototype屬性之外的所有方法和屬性,其中會生成一個__proto__屬性。__proto__屬性:1、__proto__屬性指向實。
綁定 this
返回新的對象
以下代碼演示,被隱藏的這一步
var 臨時對象 = {}臨時對象.__proo__ = vn.prototype//this賦值和指向臨時對象.heroLife = heroLife return 回去這個臨時對象
2、@Scope 顧名思義就是作用域的意思,表示這個struts2的action的作用范圍每一次調用的時候就會新建一個action,如果@Scope中的prototype換成singleton(也就是單例)就是會出現,每一次請求用同一個action。
你可以理解成: 是把上面的詳細代碼的過程給你隱藏,直接讓你得到一個綁定好原型鏈不占用內存的一個新的對象。此例中是英雄vn。
而實際上的原型鏈是一個為了不占用內存空間而尋祖的過程我們再通過一幅圖來很好的理解原型鏈!
上圖可以看到,孫悟空、 六耳獼猴用的技能實際上是菩提老祖創造出來的,他們的共有屬性是__proto__連接 ,對菩提老祖是一種尋祖的過程。
至于原型鏈的盡頭為什么是null,這里就要設計到一種哲學思想了。
總結
原型和原型鏈是JS實現繼承的一種模型。原型鏈實際上是為了節約內存的一種尋祖現象原型鏈是javascript的精妙設計 也是javascript的世界觀
?
版權聲明:本站文章均來源于網絡,如有侵權請聯系刪除!