JavaScript高級(jí)程序設(shè)計(jì)——原型和原型鏈

JS原型

前言

此文章為加深對(duì)JS中重要概念進(jìn)行理解路克,不建議沒有任何JS基礎(chǔ)的人看,只為加深對(duì)概念理解通過實(shí)際的例子养交,而不是看書以為自己讀懂了精算,可能幾天后就忘了,主要是為了理解核心概念碎连,以及對(duì)重難點(diǎn)解釋灰羽。

一切都是對(duì)象

“一切都是對(duì)象”這句話的重點(diǎn)在于如何去理解“對(duì)象”這個(gè)概念。

概念

JavaScript 中鱼辙,萬(wàn)物皆對(duì)象廉嚼!但對(duì)象也是有區(qū)別的。分為普通對(duì)象函數(shù)對(duì)象座每,Object 前鹅、Function 是 JS 自帶的函數(shù)對(duì)象。
當(dāng)然峭梳,也不是所有的都是對(duì)象舰绘,值類型就不是對(duì)象。

function show(x) {

            console.log(typeof x);    // undefined
            console.log(typeof 10);   // number
            console.log(typeof 'abc'); // string
            console.log(typeof true);  // boolean

            console.log(typeof function () {});  //function

            console.log(typeof [1, 'a', true]);  //object
            console.log(typeof { a: 10, b: 20 });  //object
            console.log(typeof null);  //object
            console.log(typeof new Number(10));  //object
        }
        show();

以上代碼列出了typeof輸出的集中類型標(biāo)識(shí)葱椭,其中上面的四種(undefined, number, string, boolean)屬于簡(jiǎn)單的值類型捂寿,不是對(duì)象。剩下的幾種情況——函數(shù)孵运、數(shù)組秦陋、對(duì)象、null治笨、new Number(10)都是對(duì)象驳概。他們都是引用類型赤嚼。

對(duì)象——若干屬性的集合

概念

數(shù)組是對(duì)象,函數(shù)是對(duì)象顺又,對(duì)象還是對(duì)象更卒。

對(duì)象里面的一切都是屬性,只有屬性稚照,沒有方法

那么這樣方法如何表示呢蹂空?——方法也是一種屬性。因?yàn)樗膶傩员硎緸殒I值對(duì)的形式果录。
而且上枕,javascript中的對(duì)象可以任意的擴(kuò)展屬性,沒有class的約束弱恒。這個(gè)大家應(yīng)該都知道辨萍,就不再?gòu)?qiáng)調(diào)了。

先說(shuō)個(gè)最常見的例子:

var obj = {
            a: 10,
            b: function(x) {
                alert(this.a + x)
            },
            c: {
                name: "yzh",
                age: 21
            }
        }

以上代碼中返弹,obj是一個(gè)自定義的對(duì)象分瘦,其中a、b琉苇、c就是它的屬性嘲玫,而且在c的屬性值還是一個(gè)對(duì)象,它又有name并扇、year兩個(gè)屬性去团。

這個(gè)可能比較好理解,那么函數(shù)和數(shù)組也可以這樣定義屬性嗎穷蛹?——當(dāng)然不行土陪,但是它可以用另一種形式,總之函數(shù)/數(shù)組之流肴熏,只要是對(duì)象鬼雀,它就是屬性的集合。

var fn = function () {
            alert(100);
        };
        fn.a = 10;
        fn.b = function () {
            alert(123);
        };
        fn.c = {
            name: "yzh",
            age: 21
        };

上段代碼中蛙吏,函數(shù)就作為對(duì)象被賦值了a源哩、b、c三個(gè)屬性——很明顯鸦做,這就是屬性的集合励烦。

(引用類型)都是對(duì)象,對(duì)象是屬性的集合泼诱。最需要了解的就是對(duì)象的概念坛掠。

創(chuàng)建對(duì)象

前言

這塊在《JS高級(jí)程序設(shè)計(jì)》也算是大章節(jié)下的一塊大內(nèi)容,我只把一些重要的概念寫出來(lái)讓大家理解,具體的深入要自己去看書中的講解屉栓。

函數(shù)和對(duì)象的關(guān)系

對(duì)象都是通過函數(shù)創(chuàng)建的

function Fn() {
            this.name = 'yzh';
            this.year = 1996;
        }
        var fn1 = new Fn();

有人可能會(huì)舉出如下反例

var obj = { a: 10, b: 20 };
var arr = [5, 'x', true];

這種做法屬于使用“快捷方式”舷蒲,在編程語(yǔ)言中,一般叫做“語(yǔ)法糖”友多。
其實(shí)以上代碼的本質(zhì)是:

//var obj = { a: 10, b: 20 };
//var arr = [5, 'x', true];

        var obj = new Object();
        obj.a = 10;
        obj.b = 20;

        var arr = new Array();
        arr[0] = 5;
        arr[1] = 'x';
        arr[2] = true;

而其中的 Object 和 Array 都是函數(shù):

console.log(typeof (Object));  // function
console.log(typeof (Array));  // function

總結(jié):對(duì)象都是通過函數(shù)來(lái)創(chuàng)建的

prototype

函數(shù)也是一種對(duì)象阿纤。他也是屬性的集合,你也可以對(duì)函數(shù)進(jìn)行自定義屬性

每創(chuàng)建一個(gè)函數(shù)夷陋,就會(huì)同時(shí)創(chuàng)建函數(shù)的prototype對(duì)象。
這個(gè)prototype的屬性值是一個(gè)對(duì)象(屬性的集合胰锌,再次強(qiáng)調(diào)F啤),默認(rèn)的只有一個(gè)叫做constructor的屬性资昧,指向這個(gè)函數(shù)本身酬土。

function Fn() { }
        Fn.prototype.name = '王福朋';
        Fn.prototype.getYear = function () {
            return 1988;
        };

        var fn = new Fn();
        console.log(fn.name);
        console.log(fn.getYear());

Fn是一個(gè)函數(shù),fn對(duì)象是從Fn函數(shù)new出來(lái)的格带,這樣fn對(duì)象就可以調(diào)用Fn.prototype中的屬性撤缴。

因?yàn)槊總€(gè)對(duì)象都有一個(gè)隱藏的屬性——“proto”,這個(gè)屬性引用了創(chuàng)建這個(gè)對(duì)象的函數(shù)的prototype叽唱。

即:fn.proto === Fn.prototype
這里的"proto"成為“隱式原型”

隱式原型

每個(gè)函數(shù)function都有一個(gè)prototype屈呕,即原型。這里再加一句話——每個(gè)對(duì)象都有一個(gè)proto棺亭,可成為隱式原型虎眨。proto用于指向創(chuàng)建它的構(gòu)造函數(shù)的原型對(duì)象

對(duì)象 person1 有一個(gè) proto屬性,創(chuàng)建它的構(gòu)造函數(shù)是 Person镶摘,構(gòu)造函數(shù)的原型對(duì)象是 Person.prototype 嗽桩,所以:

person1.proto == Person.prototype

又比如:obj這個(gè)對(duì)象本質(zhì)上是被Object函數(shù)創(chuàng)建的,因此obj.proto=== Object.prototype

在說(shuō)明“Object.prototype”之前凄敢,先說(shuō)一下自定義函數(shù)的prototype碌冶。自定義函數(shù)的prototype本質(zhì)上就是和 var obj = {} 是一樣的,都是被Object創(chuàng)建涝缝,所以它的proto指向的就是Object.prototype扑庞。

但是Object.prototype確是一個(gè)特例——它的proto指向的是null.
至于為什么簡(jiǎn)單解釋下:

所有的構(gòu)造器都來(lái)自于 Function.prototype,甚至包括根構(gòu)造器Object及Function自身拒逮。所有構(gòu)造器都繼承了·Function.prototype·的屬性及方法嫩挤。如length、call消恍、apply岂昭、bind

console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype)   // object
console.log(typeof Number.prototype)   // object
console.log(typeof Boolean.prototype)  // object
console.log(typeof String.prototype)   // object
console.log(typeof Array.prototype)    // object
console.log(typeof RegExp.prototype)   // object
console.log(typeof Error.prototype)    // object
console.log(typeof Date.prototype)     // object
console.log(typeof Object.prototype)   // object

知道了所有構(gòu)造器(含內(nèi)置及自定義)的proto都是Function.prototype,

Function.prototype的proto是誰(shuí)呢

console.log(Function.prototype.proto === Object.prototype) // true
這說(shuō)明所有的構(gòu)造器也都是一個(gè)普通 JS 對(duì)象约啊,可以給構(gòu)造器添加/刪除屬性等邑遏。同時(shí)它也繼承了Object.prototype上的所有方法:toString、valueOf恰矩、hasOwnProperty等记盒。

最后Object.prototype的proto是誰(shuí)?

Object.prototype.proto === null // true
已經(jīng)到頂了外傅,為null纪吮。

原型鏈

概念

訪問一個(gè)對(duì)象的屬性時(shí),先在基本屬性中查找萎胰,如果沒有碾盟,再沿著proto這條鏈向上找

javascript中的繼承是通過原型鏈來(lái)體現(xiàn)的.

傳統(tǒng)原型語(yǔ)法

function Foo() {}

        Foo.prototype.a = 100;
        Foo.prototype.b = 200;
        var f1 = new Foo();
        f1.a = 10;
        alert(f1.a);  //10
        alert(f1.b);  //200
function Foo() {}
        var f1 = new Foo();
        f1.a = 10;
        Foo.prototype.a = 100;
        Foo.prototype.b = 200;
        
        alert(f1.a);  //10
        alert(f1.b);  //200

對(duì)象字面量方法添加屬性和方法的注意事項(xiàng)

function Foo() {}

        Foo.prototype = {
            a: 100,
            b: 200
        }
        var f1 = new Foo();
        f1.a = 10;
        alert(f1.a); //10
        alert(f1.b); //200
function Foo() {}
        var f1 = new Foo();
        f1.a = 10;
        Foo.prototype = {
            a: 100,  
            b: 200
        }
        
        alert(f1.a);  //10
        alert(f1.b);  //undefined

原型的屬性和方法賦值要在,新建實(shí)例對(duì)象之前技竟,不然無(wú)法獲得原型的值和屬性冰肴,alert返回相應(yīng)的undefined

重寫原型對(duì)象問題

接上面的例子講,如果在實(shí)例上添加新屬性,這個(gè)屬性就會(huì)屏蔽原型對(duì)象中保存的同名屬性榔组,就是阻止訪問了屬性熙尉,而不是修改原型的屬性。

function Foo() {}
        var f1 = new Foo();
        f1.a = 10;
        Foo.prototype = {
            a: 100,  
            b: 200
        }
        
        alert(f1.a);  //10
        alert(f1.b);  //undefined

總結(jié):重寫原型對(duì)象切斷了現(xiàn)有原型與任何之前已經(jīng)存在的對(duì)象實(shí)例之間的關(guān)系搓扯,它們的引用的仍然是最初的原型检痰。

End

暫時(shí)總結(jié)到此,有些知識(shí)點(diǎn)沒有講到锨推,可能需要大家自己去看書或查閱資料來(lái)理解攀细,本人理解也有限,文中若有難以理解的還望大神換個(gè)方式來(lái)闡述爱态。

未完待續(xù)

后續(xù)還有兩篇講解《執(zhí)行上下文與作用域》和《閉包》谭贪,最后一篇閉包可能會(huì)有一些前端面試題來(lái)講,并在文章末做個(gè)總結(jié)锦担。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末俭识,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洞渔,更是在濱河造成了極大的恐慌套媚,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磁椒,死亡現(xiàn)場(chǎng)離奇詭異堤瘤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)浆熔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門本辐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事慎皱±铣妫” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵茫多,是天一觀的道長(zhǎng)祈匙。 經(jīng)常有香客問我,道長(zhǎng)天揖,這世上最難降的妖魔是什么夺欲? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮今膊,結(jié)果婚禮上些阅,老公的妹妹穿的比我還像新娘。我一直安慰自己万细,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布纸泄。 她就那樣靜靜地躺著赖钞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪聘裁。 梳的紋絲不亂的頭發(fā)上雪营,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音衡便,去河邊找鬼献起。 笑死,一個(gè)胖子當(dāng)著我的面吹牛镣陕,可吹牛的內(nèi)容都是我干的谴餐。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼呆抑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岂嗓!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鹊碍,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤厌殉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后侈咕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體公罕,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年耀销,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了楼眷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖摩桶,靈堂內(nèi)的尸體忽然破棺而出桥状,到底是詐尸還是另有隱情,我是刑警寧澤硝清,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布辅斟,位于F島的核電站,受9級(jí)特大地震影響芦拿,放射性物質(zhì)發(fā)生泄漏士飒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一蔗崎、第九天 我趴在偏房一處隱蔽的房頂上張望酵幕。 院中可真熱鬧,春花似錦缓苛、人聲如沸芳撒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)笔刹。三九已至,卻和暖如春冬耿,著一層夾襖步出監(jiān)牢的瞬間舌菜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工亦镶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留日月,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓缤骨,卻偏偏與公主長(zhǎng)得像爱咬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绊起,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容