secrets of the javascript Ninja (Function Prototypes)(javascript忍者的秘密)
函數原型有很多用途,比如可以用來向一個函數實例上添加一些屬性,但是它的一個最主要用途是使JavaScript能夠以麵向對象的方式編程。
實例化和原型(Instantiation 和 prototypes)
所有函數默認的都會有一個含有空對象的prototype屬性,它的這個特性隻有在實例化後才會有用,為了能夠理解它的這種特性是多麼的重要,需要知道一個重要的原則:函數具有雙重功能,它可以作為一個平常的函數,也可以作為一個類。
我們可以通過下麵一個小例子來看看如何使用prototype屬性向一個函數上添加一個功能- function Ninja(){} Ninja.prototype.swingSword=function(){ return true; } var ninja=Ninja(); alert(ninja);//undefined,說明不是Ninja的一個實例 var ninja2=new Ninja(); alert(ninja2.swingSword);//true
- 從上麵的這個例子,我們可以發現以下兩個問題:
1.為了產生一個函數的實例對象必須使用new操作符調用該函數。
2.swingSword變成了Ninja的實例ninja2的一個屬性。
對於函數Ninja來說,由於使用new操作符調用它,我們也可以認為他是一個構造函數。這就意味著,它使用new操作符調用函數的時候,該函數中this所指向的上下文就是對象自身的實例(即和prototype相同),這段話不是太好理解,來讓我們看一個例子:
function Ninja(){ this.swung = false; // Should return true this.swingSword = function(){ return !this.swung; }; } // Should return false, but will be overridden Ninja.prototype.swingSword = function(){ return this.swung; }; var ninja = new Ninja(); alert(ninja.swingSword());
從上麵的例子我們可以發現實例對象調用它的同名方法的順序:
1.綁定在prototype上的屬性。
2.綁定在構造函數內的屬性。
另外一個需要了解的是綁定在prototype上的屬性,他可以被更新和改變,即使一個對象被實例化後:如下
function Ninja(){ this.swung = true; } var ninja = new Ninja(); Ninja.prototype.swingSword = function(){ return this.swung; }; alert(ninja.swingSword());
對象類型
還是以例子說話:
function Ninja(){} var ninja = new Ninja(); alert(typeof ninja); alert(ninja instanceof Ninja); alert(ninja.constructor == Ninja);
從上麵的例子中,我們可以看到:
1.所有的示例對象如果使用typeof檢測都是object類型
2.instanceof 實例對象是由那個函數生成的。
3.任何實例都有個constructor屬性,用來引用生成該實例對象的構造函數。
為了證明第三個觀點,下麵來看一個簡單的例子:
var ninja = new Ninja(); var ninja2 = new ninja.constructor(); alert(ninja2 instanceof Ninja);//true
繼承與prototype鏈
在這裏我們還可以看到instanceof的一個重要特性:
function Person(){} Person.prototype.dance = function(){}; function Ninja(){} // Achieve similar, but non-inheritable, results Ninja.prototype = Person.prototype; Ninja.prototype = { dance: Person.prototype.dance }; // Only this maintains the prototype chain Ninja.prototype = new Person(); var ninja = new Ninja(); alert(ninja instanceof Ninja);//true alert(ninja instanceof Person);//true alert(ninja instanceof Object);//true
有很多方法從函數的prototype屬性上複製功能(方法和函數),但是隻有一種情況能夠形成prototype鏈。即:SubFunction.prototype = new SuperFunction();.
HTML prototypes
在Internet Explorer 8, Firefox, Safari, 和 Opera這些瀏覽器中這些可以使用prototype擴展dom元素: 來看看一個簡短的例子:
<div >I'm going to be removed.</div> <div >Me too!</div> HTMLElement.prototype.remove = function(){ if ( this.parentNode ) this.parentNode.removeChild( this ); }; // Old way var a = document.getElementById("a"); a.parentNode.removeChild( a ); // New way document.getElementById("b").remove();
最後更新:2017-04-02 00:06:44