關於JS的prototype

目錄:

概述:

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

初步理解:

在說prototype和constructor之前我們先得看幾個例子。
1
2
3
4
function name(obj){
    alert(obj)//"uw3c"
}
name("uw3c")
這是個普通的自調用的例子,大家都能理解,那麼看下一個例子:
1
2
3
4
5
function name(obj){
    alert(obj)//"uw3c"
}
var test = new name("uw3c")
test();
許久不見的new來了,new的作用就是"構造函數",這種方法與直接聲明的函數的區別就是:用new操作符構造出來的函數是一個對象,我們接着看下面的例子:
1
2
3
4
5
function uw3c(){
}
var test = new uw3c();
alert(typeof uw3c);//function
alert(typeof test);//object
uw3c是個函數,而test是個對象,那麼除了類型不一樣,還有什麼不一樣呢?
1
2
3
4
5
6
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函數本身。 是不是很繞?用僞代碼表示如下:
1
2
3
4
5
var function{
    prototype:prototype{
                constructor:constructor == function
              }
}
還不明白?看圖吧:
JS原型

prototype的作用:

這個prototype到底有什麼作用呢?看下面的例子:
1
2
3
4
5
function uw3c(){
}
uw3c.prototype.name = "a";
var test = new uw3c();
alert(test.name)//"a";
奇怪吧,明明沒有爲test設置name屬性,可是爲什麼會有值?
這就是prototype的功勞了,uw3c中prototype屬性中的name對象,在uw3c被new構造函數之後,被繼承到了對象test的屬性中。接着看:
1
2
3
4
5
6
7
var name = "js";
function uw3c(name){
    alert(this.name);//"css"
}
uw3c.prototype.name = "css";
var test = new uw3c();
test();
爲什麼alert的值不是“js”?這個過程大致如下:
1
2
var test={};
uw3c.call(test);
第一步是建立一個新對象(test)。
第二步將該對象(test)內置的原型對象設置爲構造函數(就是uw3c)prototype 屬性引用的那個原型對象。
第三步就是將該對象(test)作爲this 參數調用構造函數(就是uw3c),完成成員設置等初始化工作。
其中第二步中出現了一個新名詞就是內置的原型對象,注意這個新名詞跟prototype對象不是一回事, 爲了區別我叫它inobj,inobj就指向了函數uw3c的prototype對象。在uw3c的prototype對象中出現的任何屬性或者函數都可以在test對象中直接使用,這個就是JS中的原型繼承了。

prototype是繼承還是克隆:

看了上面的,有些人可能會認爲構造一個函數是複製了原函數的prototype的屬性,在這裏大家注意一下,是繼承不是複製,請看下方的代碼:
1
2
3
4
5
6
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有什麼用處,它有什麼優點?看下面代碼:
1
2
3
4
5
6
7
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既能保留公有性,又能具有私有性。
發佈了27 篇原創文章 · 獲贊 8 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章