首頁  >  文章  >  web前端  >  Javascript中的Prototype到底是什麼_javascript技巧

Javascript中的Prototype到底是什麼_javascript技巧

WBOY
WBOY原創
2016-05-16 15:15:111646瀏覽

Javascript也是物件導向的語言,但它是一種基於原型Prototype的語言,而不是基於類別的語言。在Javascript中,類別和物件看起來沒有太多的區別。

什麼是prototype:

function定義的物件有一個prototype屬性,prototype屬性又指向了一個prototype對象,注意prototype屬性與prototype對像是兩個不同的東西,要注意區別。在prototype物件中又有一個constructor屬性,這個constructor屬性同樣指向一個constructor對象,而這個constructor物件恰恰就是這個function函數本身。 是不是很繞?用偽代碼表示如下:

var function{
prototype:prototype{
constructor:constructor == function
}
}

還不明白?看圖吧:


prototype的作用:

這個prototype到底有什麼作用呢?看下面的範例:

function jb51(){
}
jb51.prototype.name = "a";
var test = new jb51();
alert(test.name)//"a";

奇怪吧,明明沒有為test設定name屬性,可是為什麼會有值?

這就是prototype的功勞了,uw3c中prototype屬性中的name對象,在uw3c被new建構子之後,被繼承到了對象test的屬性中。接著看:

var name = "js";
function jb51(name){
alert(this.name);//"css"
}
jb51.prototype.name = "css";
var test = new jb51();
test()

為什麼alert的值不是「js」?這個過程大致如下:

var test={};
uw3c.call(test);

第一步是建立一個新物件(test)。

第二步驟將該物件(test)內建的原型物件設定為建構子(就是uw3c)prototype 屬性所引用的那個原型物件。

第三步是將該物件(test)當作this 參數呼叫建構函式(就是uw3c),完成成員設定等初始化工作。

其中第二步驟出現了一個新名詞就是內建的原型對象,注意這個新名詞跟prototype對像不是一回事, 為了區別我叫它inobj,inobj就指向了函數uw3c的prototype對象。在uw3c的prototype物件中出現的任何屬性或函數都可以在test物件中直接使用,這個就是JS中的原型繼承了。

通常,這樣建立一個物件:

function person(name){
this.sayHi = function(){
alert('hi ' + this.name);
}
this.name = name;
}
var p = new person("dan");
p.sayHi(); 

以上,使用new關鍵字,透過物件(函數也是特殊物件)建立一個物件實例。

在基於類別的語言中,屬性或欄位通常都是在類別中事先定義好了,但在Javascript中,在建立物件之後還可以為類別新增欄位。

function animal(){}
var cat = new animal();
cat.color = "green"; 

以上,color這個欄位只屬於目前的cat實例。
對於後加的字段,如果想讓animal的所有實例都擁有呢?

--使用Prototype
function animal(){}
animal.prototype.color= "green";
var cat = new animal();
var dog = new animal();
console.log(cat.color);//green
console.log(dog.color);//green 

透過Prototype不僅可以新增字段,還可以新增方法。

function animal(){}
animal.prototype.color= "green";
var cat = new animal();
var dog = new animal();
console.log(cat.color);//green
console.log(dog.color);//green
animal.prototype.run = funciton(){
console.log("run");
}
dog.run(); 

原來透過prototype屬性,在創建物件之後還可以改變物件的行為。
例如,可以為數組這個特殊物件添加一個方法。

Array.prototype.remove = function(elem){
var index = this.indexof(elem);
if(index >= 0){
this.splice(index, 1);
}
}
var arr = [1, 2, 3] ;
arr.remove(2); 

除了透過prototype為物件定義屬性或方法,還可以透過物件的建構子來定義類別的屬性或方法。

function animal(){
this.color = "green";
this.run = function(){
console.log("run");
}
}
var mouse = new animal();
mouse.run(); 

以上做法的也可以讓所有的animal實例共用所有的欄位和方法。並且還有一個好處是可以在建構函式中使用類別的局部變數。

function animal(){
var runAlready = false;
this.color = "green";
this.run = funciton(){
if(!runAlreadh){
console.log("start running");
} else {
console.log("already running")
}
}
} 

其實,一個更實際的做法是把透過建構函式結合透過prototype定義一個類別的欄位和行為。

function animal(){
var runAlready = false;
this.run = function(){
if(!runAlready){
console.log('i am running');
} else {
console.log("i am already running");
}
}
}
animal.prototype.color = '';
animal.prototype.hide = funciton(){
console.log("");
}
var horse = new animal();
horse.run();
horse.hide(); 

Prototype允許我們在創建物件之後來改變物件或類別的行為,並且這些透過prototype屬性添加的欄位或方法所有物件實例是共享的。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn