javascript原型詳解

相信很多人都很困惑于javascript的原型系統,,在我剛開始接觸javascript的原型系統的時候,我也非常困惑于它的結構,因為我以前都沒有接觸過這種基于原型的語言。javascript是一個基于原型的語言,雖然是以函數為第一等公民的語言,但也可以實現面向對象,那就是基于它的原型系統。

javascript原型之函數

現在我們來寫一個函數

function A(){

}

這是一個內容為空的函數,但它真的內容為空嗎?讓我們來看下面一段代碼

function A(){

}

console.log(A.toString());;//輸出為function A() {}

我們知道,javascript里面的一切都是對象,函數也是,既然函數是對象那么就可以調用函數對象的方法,所以我試著調用了toString 方法,它輸出了一個字符串,證明toString方法是存在的。那么toString 方法到底是存在在那里呢,不存在于函數體里,那么存在一個地方必然有toString的函數體且對象function A以某種方式獲得了toString方法的調用權。。。

我百度了一下基于原型的語言的特征,基于原型的語言,必然有一個或著多個最初的對象,然后以后的對象都是由這些最初對象克隆過來的,也就是說,基于原型的語言中對象的生成是根據存在的對象來復制的。

好,那我們開始下一步的實驗

function A(){

}
console.log(A.__proto__);//Function
console.log(A.prototype);//{}

我輸出了Javascript對象所擁有的兩個屬性,這是javascript語言規定的兩個屬性_proto_屬性指向對象構造函數的原型(不是很理解),prototype屬性指向對象的原型。從結果看A函數構造函數的原型是Function,A函數自己的原型是{ }(同樣不是很理解)

于是我又做了下面這個實驗

Function.prototype.getName = function(){
    return "FunctionTest";
}

function A(){

}
console.log(A.__proto__ === Function.prototype);//true
console.log(A.getName());//FunctionTest

function B(){

}
console.log(B.__proto__ === Function.prototype);//true
console.log(B.getName());//FunctionTest

console.log(A.__proto__ === A.constructor.prototype);//true
//即函數作為對象它的構造函數為Function

我從另外的地方得知javascript里面有內建的Function和Object對象,于是我想著Function對象是否和function A 有些關聯呢,當我看到第一條console.log語句返回true的時候,我知道我是正確的,于是我擴展了Function.prototype 給其中添加了getName方法,然后我在用函數A調用了這個方法返回FunctionTest,我又新建了函數B,也調用了這個方法,返回FunctionTest。

至此我知道了函數_proto屬性的指向,指向其構造函數的原型,當對象A調用getName函數的時候,由于A對象沒有getName函數,javascript會尋找對象A的_proto屬性所對應對象,有則調用,沒有則繼續向上找。

函數的prototype屬性我一開始始終沒有找到與之對應的對象

console.log(A.prototype === Function.__proto__);//false
console.log(A.prototype === Function.prototype);//false
console.log(A.prototype === Object.__proto__);//false
console.log(A.prototype === Object.prototype);//false

后來我換了一種思考方式終于找到了

console.log(A.prototype.__proto__ === Object.prototype);//true
console.log(A.prototype.prototype);//undefined

而之后我又實驗了

console.log(Function.prototype.__proto__ === Object.prototype);

所以最終所有的一切對象的內置函數比如toString都是在Object.prototype里的

然后我又有一個猜測
所有一切函數對象的內置函數比如call,apply都是Function.prototype里的,可以很容易的就驗證,普通對象是不能調用call,apply的。

javascript原型之對象

我實驗了如下的代碼

function A(){
    this.getText = function(){
        return "Text";
    }
}

A.prototype.getName = function(){
    return "my god";
}

var i = new A();

console.log(i.getText());//Text
console.log(i.getName());//my god

然后我改了一下程序

function A(){
    this.getName = function(){
      return "Text";
    }
}

A.prototype.getName = function(){
    return "my god";
}

var i = new A();

console.log(i.getName());//Text
console.log(i.__proto__ === A.prototype);//true
console.log(i.prototype);//undefined

由上面的實驗可知,由函數A作為構造函數,所克隆出來的普通對象i的_proto_屬性指向函數A的原型(也就是prototype屬性),且普通對象i的prototype屬性是沒有定義的。

當i調用getName函數時,由于i是由函數A克隆出來(大家還沒忘記原型語言的特征吧,就是新的對象是由另一個已存在的對象克隆的)的,里面只用getText函數沒有getName函數,于是javascript就會尋找i的_proto_屬性,而i的proto屬性所指向的其實就是A.prototype,所以javascript就在A.prototype里面找getName函數,找到了就調用。所以第二段代碼中優先調用返回Text的那個getName函數。

javascript里面還有一種對象就是對象字面量,對象字面量的是否擁有Function.prototype或者Object.prototype的函數呢
請看實驗

var a = {
    getName:function(){
        return "a";
    }
}
console.log(a.__proto__);//{}
console.log(a.prototype);//undefined

console.log(a.__proto__ === Object.prototype);//true

由于對象字面量不是由函數對象克隆的,所以沒有Function.prototype里面的方法,因為a._proto_指向的是Object.prototype,這就說明javascript只能在a本身和Object.prototype里面找調用的函數。

總結

由上面以一些內容我們可以得出:

1.javascript函數調用順序是查找對象的原型(即,對象的_proto_屬性),一層一層的往上找,直到遇到該函數或者undefined才停止。

2.函數作為特殊的對象,它的原型是Function.prototype,能夠調用Function.prototype里面的方法,而Function.prototype的原型又是Object.prototype,故而函數對象既能調用Function.prototype里面的方法,還能調用Object.prototype里面的方法,這就說函數對象即是“函數”又是對象。

3.普通對象的原型是其構造函數的原型(即,A.prototype),而A.prototype的原型是Object.prototype,所以,普通對象只能調用它本身和Object.prototype內的函數

4.對象字面量的原型是Object.prototype。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內容