關於JS的prototype

在接觸JS的過程中,隨著理解的深入會逐漸的理解一些比較深奧的理論或者知識,那麼今天我們來介紹一下比較難理解的prototype和constructor。

初步理解:

在說prototype和constructor之前我們先得看幾個例子。

function name(obj){

alert(obj)//"uw3c"

}

name("uw3c")

這是個普通的自調用的例子,大家都能理解,那麼看下一個例子:

function name(obj){

alert(obj)//"uw3c"

}

var test = new name("uw3c")

test();

許久不見的new來了,new的作用就是"構造函數",這種方法與直接聲明的函數的區別就是:用new操作符構造出來的函數是一個對象,我們接著看下面的例子:

function uw3c(){

}

var test = new uw3c();

alert(typeof uw3c);//function

alert(typeof test);//object

uw3c是個函數,而test是個對象,那麼除了類型不一樣,還有什麼不一樣呢?

function name(){

alert(JSON.stringify(name.prototype))//{},是個空對象

}

name();

var test = new name();

alert(JSON.stringify(test.prototype))//undefined,不存在這個對象

相信大家也看出來了,直接聲明的函數 擁有prototype這個屬性,而new 構造出來的函數不存在prototype這個屬性象。

什麼是prototype:

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

var function{

prototype:prototype{

constructor:constructor == function

}

}

prototype的作用:

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

function uw3c(){

}

uw3c.prototype.name = "a";

var test = new uw3c();

alert(test.name)//"a";

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

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

var name = "js";

function uw3c(name){

alert(this.name);//"css"

}

uw3c.prototype.name = "css";

var test = new uw3c();

test();

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

var test={};

uw3c.call(test);

第一步是建立一個新對象(test)。

第二步將該對象(test)內置的原型對象設置為構造函數(就是uw3c)prototype 屬性引用的那個原型對象。

第三步就是將該對象(test)作為this 參數調用構造函數(就是uw3c),完成成員設置等初始化工作。

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

prototype是繼承還是克隆:

看了上面的,有些人可能會認為構造一個函數是複製了原函數的prototype的屬性,在這裡大家注意一下,是繼承不是複製,請看下方的代碼:

function uw3c(){

}

uw3c.prototype.name = "b";

var test = new uw3c();

alert(JSON.stringify(test));//{}

alert(test.name);//"b"

如果是克隆應該能打印出test的一個屬性name,但是並沒有,可是卻能打印出test.name,所以是test繼承了uw3c.prototype的屬性。

prototype的優點:

講了這麼多,大家肯定會問,prototype有什麼用處,它有什麼優點?看下面代碼:

function uw3c(name){

alert("姓名:" + name + ",年齡:" + this.age + ",性別:" + this.sex);

}

uw3c.prototype.age = 15;

uw3c.prototype.sex = "man";

var test1 = new uw3c("css");//姓名:css,年齡:15,性別:man

var test2 = new uw3c("js");//姓名:js,年齡:15,性別:man

看完這個例子大家應該明白了,使用prototype既能保留公有性,又能具有私有性。


分享到:


相關文章: