在接觸JS的過程中,随着了解的深入會逐漸的了解一些比較深奧的理論或者知識,那麼今天我們來介紹一下比較難了解的prototype和constructor。
初步了解:
在說prototype和constructor之前我們先得看幾個例子。
function name(obj){
alert(obj)//"uw3c"
}
name("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到底有什麼作用呢?看下面的例子:
uw3c.prototype.name = "a";
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";
為什麼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的屬性,在這裡大家注意一下,是繼承不是複制,請看下方的代碼:
uw3c.prototype.name = "b";
alert(JSON.stringify(test));//{}
alert(test.name);//"b"
如果是克隆應該能列印出test的一個屬性name,但是并沒有,可是卻能列印出test.name,是以是test繼承了uw3c.prototype的屬性。
prototype的優點:
講了這麼多,大家肯定會問,prototype有什麼用處,它有什麼優點?看下面代碼:
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既能保留公有性,又能具有私有性。