在 JavaScript 中,每個函數對象都有一個默認的屬性 prototype,稱為函數對象的原型成員,這個屬性指向一個對象,稱為函數的原型對象,當我們每定義了一個函數的時候,JavaScript 就創建了一個對應的原型對象,也就是說,當我們定義一個函數的時候,實際上得到了兩個對象,一個函數對象,一個原型對象。原型對象是一個特殊的對象,函數的 prototype 成員指向它的原型對象。
可以通過函數對象的 prototype 成員取得這個原型對象的引用。
下面定義一個函數對象 Person,然后通過 prototype 來取得它的原型對象。然后在它的原型對象上定義了一個方法。
function Person()
{
}
Person.prototype.showPerson = function()
{
alert( “Person Object.”);
}
var alice = new Person();
alice.showPerson();
這個原型對象上定義的成員將用來共享給所有通過這個函數創建的對象使用。相當于 C# 中的實例方法,對象,函數和原型在內存中的關系如下圖所示:
每個對象也都有一個原型成員 prototype,通過 new 函數創建的對象會通過函數的 prototype 找到函數的原型,然后將自己的原型指向這個對象。對于不是通過函數創建的對象實例和原型對象,它們的原型會被設置為 Object 函數的原型對象。
Object 函數對象是 JavaScript 中定義的頂級函數對象,在 JavaScript 中所有的對象都直接或者間接地使用 Object 對象的原型。
當訪問對象的屬性或者方法的時候,如果對象本身沒有這個屬性或者方法,那么,JavaScript 會檢查對象的 prototype 對象是否擁有這個屬性或者方法,如果有,則作為對象的屬性或者方法返回,如果沒有,那么將通過原型對象的 prototype 繼續進行檢查,直到原型對象為 Object 函數的原型對象為止。
但是 prototype 是一個特殊的屬性,在大多數的瀏覽器上,例如 IE 瀏覽器,都不能直接訪問對象的 prototype 成員。返回的結果為 undefined。不能賦予對象一個新的原型,只能通過創建它的函數來確定對象的原型。
函數對象的原型有一個特殊的用途,就是通過函數 new 創建出來的對象,會自動將函數對象的原型賦予新創建出的對象的原型。這樣,如果為某個函數設置了原型對象,那么,所有通過這個函數創建的對象將擁有同樣的原型對象。通過這個方法,可以使這些對象共享相同的屬性或者方法,來模擬類型的概念。
在 jQuery 中,我們經常使用的 $ 函數就是定義在 window 對象上的 $ 函數。
其代碼如下:
24 jQuery = window.jQuery = window.$ = function( selector, context ) {
25 // The jQuery object is actually just the init constructor 'enhanced'
26 return new jQuery.fn.init( selector, context );
27 },
這個函數實際上通過 new jQuery.fn.init( selector, context )來完成,也就是通過 init 函數創建了一個對象。
在 541 行重新指定了函數 init 的原型對象。所以 init 函數的原型對象就是 fn 對象。
540 // Give the init function the jQuery prototype for later instantiation
541 jQuery.fn.init.prototype = jQuery.fn;
這樣所有通過 $ 創建出來的對象都將共享 fn 對象上的成員。因此,jQuery 對象都有了類似 attr 、html 等等方法了。
參考資料:
李戰 悟透javascript
來源:博客園