首先,原型是乙個物件。而且所有的物件都有乙個原型(有一種例外:當把物件的原型設為null時),並且任何物件都可以成為乙個原型。
當我們定義乙個物件時var a = new object();
預設的原型在原型鏈的頂端。
原型最大的好處體現在它的共享
的特性。所有原型物件的例項物件共享它所包含的屬性和方法。所以我們常用利用原型來建立物件,也就是原型模式
。
原型模式
是一種用來建立多個例項物件的方法,我們常常把它和建構函式
結合起來用來建立特定型別的物件。
我們建立的每乙個函式都有乙個prototype
屬性,這個屬性是乙個指標,指向乙個物件。這個物件的用途是包含可以由特定型別的所有例項共享的屬性和方法。這個物件就是實際上通過呼叫建構函式而建立的例項物件
的原型物件。看**:
// 建構函式
function person(){};
person.prototype.name = "darko";
person.prototype.age = 21;
person.prototype.sayname = function()
var person1 = new person();
person1.sayname(); // "darko"
var person2 = new person();
person2.sayname(); // "darko"
我們將所有的屬性和sayname()
方法新增到了建構函式person
的prototype
屬性中,建構函式成了空函式。但是即便如此,我們也可以通過呼叫建構函式來建立新物件,而且新物件還會具有相同的屬性和方法。
例項物件就是通過建構函式創造的,預設擁有乙個constructor
屬性指向其建構函式。
原型物件就是建構函式的屬性prototype
指向的那個物件,同時也是基於建構函式生成的例項物件的原型物件。在預設情況下,所有的原型物件都會自動獲得乙個constructor
屬性,這個屬性是乙個指標,指向其建構函式。
例項物件可以訪問原型物件上的屬性和方法。在例項物件的內部有乙個屬性(內部屬性)[[prototype]]
指向其原型物件。有一種非標準方法__proto__
訪問[[prototype]]
。
在上面的例子中person1
和person2
就是例項物件,建構函式為person
,原型物件為person.prototype
。
來,看個栗子(還是上面那段**):
alert(person1.constructor === person); // true
alert(person.prototype.constructor === person); // true
alerta(person1.__proto__ === person.prototype); // true
來看個圖你就什麼都懂了:
prototype
是函式的乙個預設屬性,只有函式物件才有
object.getprototypeof()
方法用來返回例項物件內部屬性[[prototype]]
的值。這是es5中定義的用來獲取原型物件的標準方法。
__proto__
屬性是獲取原型物件的非標準方法(ie不支援)
看個栗子(還是上面那段**):
alert(object.getprototypeof(person1) === person.prototype); // true
alert(object.getprototypeof(person1).name); // "darko"
alert(person1.__proto__ === person.prototype); // true
alert(person1.__proto__.name); // "darko"
若例項物件中屬性和其指向的原型物件的屬性重名,例項物件中的屬性遮蔽原型物件中的那個屬性。
舉個栗子:
function person(){};
person.prototype.name = "darko";
person.prototype.age = 21;
person.prototype.sayname = function()
var person1 = new person();
var person2 = new person();
person1.name = "leon";
person1.sayname(); // "leon",來自例項
person2.sayname() // "darko",來自原型
delete person1.name;
person1.sayname(); // "darko",來自原型
可以利用hasownproperty()
方法判斷乙個屬性是位於例項中,還是原型中。只有在屬性來自例項中時,才會返回true
。通常和in
操作符配合使用。
// 接上
alert("name" in person1); // true
alert(person1.hasownproperty("name")); // false
所有的原生引用型別都在其原建構函式的原型上定義了方法,例如,array.prototype.sort()
方法,正是由於原型的共享特性,我們定義的陣列才可以使用sort()
方法等一系列的方法。
舉個栗子:
var num = [1, 5, 3, 7, 9];
num.sort(); // 1,3,5,7,9
alert(num.constructor === array); // true
alert(num.__proto__ === array.prototype); // true
alert(num.__proto__.__proto__ === object.prototype); //true
陣列物件num
本身就是構造器array
的例項物件,而array
的prototype
屬性指向的物件上定義了sort()
方法,所以新定義了num
物件經過搜尋找到了sort()
方法,並呼叫了方法。
由於在原型中查詢值的過程是一次搜尋,所以對原型物件的任何修改都能立即從例項上反應出來。
舉個栗子:
function person(){};
var firend = new person();
// 修改原型
person.prototype.sayhi = function()
firend.sayhi(); // "hi"
但是若將原型重寫,來看看有什麼不同:
function person(){};
person.prototype.name = "darko";
var firend = new person();
// 重寫了原型物件
person.prototype =
}alert(friend.name); // "darko"
firend.sayhi(); // error
這說明,重寫原型物件切斷了現有原型和任何之前已經存在的例項物件之間的聯絡,它們引用的仍是最初的原型。
如果你覺得我寫的還可以,點一下推薦吧。
JavaScript 學習總結
初學起來覺得知識點很多很雜,很多框架的構建都加入了自己的主觀色彩,沒有完全按照教程的來總結,所以難免有些地方看起來會很奇怪。剛開始都不是完美的,慢慢來,不斷地去完善自己。基本變數型別 4種 複雜變數型別 2種 typeof 檢視變數型別 定義乙個物件 var person 清空乙個物件 var pe...
JavaScript學習總結1
我是切割線 的開始 利用prototype屬性能夠加入公有屬性和方法 function myconstructor2 宣告建構函式,能夠使用物件字面量語法來向prototype屬性中加入全部公有成員 myconstructor2.prototype methodb function var myco...
JavaScript的學習總結
隨著一階段的結束,開始二階段js的學習。首先,要學會接受適應這個轉變,積極調整個人狀態。js更加注重邏輯思維,重在理解練習。學習過程中遇到苦難不足為奇,這個過程本就不是一帆風順的。不能因為遇到一點點苦難就隨便想著放棄,如此,即背叛了來千鋒學習的初衷。拼搏到無能為力,堅持到感動自己 這句話牢記心中,落...