對原型和原型鏈的理解

背景介紹

1.構(gòu)造函數(shù)

構(gòu)造函數(shù) ,是一種特殊的方法。主要用來在創(chuàng)建對象時初始化對象。每個構(gòu)造函數(shù)都有prototype(原型)屬性

2.原型模式

每個函數(shù)都有prototype(原型)屬性,這個屬性是一個指針,指向一個對象费什,這個對象的用途是包含特定類型的所有實(shí)例共享的屬性和方法,即這個原型對象是用來給實(shí)例共享屬性和方法的手素。

而每個實(shí)例內(nèi)部都有一個指向原型對象的指針鸳址。

原型鏈

每個構(gòu)造函數(shù)都有一個原型對象,原型對象都包含一個指向構(gòu)造函數(shù)的指針泉懦,而實(shí)例都包含指向原型對象內(nèi)部的指針稿黍。我們讓原型對象的實(shí)例(1)等于另一個原型對象(2),

此時原型對象(2)將包含一個指向原型對象(1)的指針,

再讓原型對象(2)的實(shí)例等于原型對象(3)祠斧,如此層層遞進(jìn)就構(gòu)成了實(shí)例和原型的鏈條闻察,這就是原型鏈的概念

構(gòu)造函數(shù)

構(gòu)造函數(shù) ,是一種特殊的方法琢锋。主要用來在創(chuàng)建對象時初始化對象辕漂。 即為對象變量賦初始值。每個構(gòu)造函數(shù)的實(shí)例都將共享構(gòu)造函數(shù)的初始值吴超。 構(gòu)造函數(shù)的出現(xiàn)是為了解決使用Object構(gòu)造函數(shù)和字面量表示法不方便創(chuàng)建大量重復(fù)對象的問題钉嘹。

傳統(tǒng)創(chuàng)建對象實(shí)例的方法

? var person={

? ? ? name:'張女士',

? ? ? age:'80',

? ? ? gender:'女'

? };

console.log(person)

注:這個方法如果用于創(chuàng)建大量相同屬性和方法的對象時,會產(chǎn)生大量重復(fù)代碼

構(gòu)造函數(shù)的方法

? ? //構(gòu)造函數(shù)方法創(chuàng)建對象實(shí)例

? ? function Person(name,age,gender) {

? ? this.name=name;

? ? this.age=age;

? ? this.gender=gender;

? ? this.say=function () {

? ? alert(this.name)

? ? ? ? ? }

? ? }

? ? var person1=new Person('鐘女士',80,'女');

? ? var person2=new Person('張女士',80,'女');

? ? console.log(person2)

? ? console.log(person1)

原型模式

使用構(gòu)造函數(shù)的問題是鲸阻,每個方法都要在每個實(shí)例上重新創(chuàng)建一遍跋涣,即在構(gòu)造函數(shù)的不同實(shí)例上的同名函數(shù)是不相等的。而我們創(chuàng)建每個構(gòu)造函數(shù)都有一個prototype(原型)屬性鸟悴,這個屬性是個指針陈辱,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法细诸,我們使用這個原型對象來共享實(shí)例的屬性和方法的模式就叫原型模式

? //原型模式創(chuàng)建對象

function Person(){

}

Person.prototype.name='鐘女士';

Person.prototype.age=80;

Person.prototype.gender='女';

var person1= new Person();

console.log(person1)

//簡寫原型模式

Person.prototype={

? constructor:Person

? name:'鐘女士'沛贪,

? age:80,

? gender:'女'

}

注:每個原型對象都有constructor屬性,由于簡寫模式重寫了默認(rèn)的prototype對象震贵,所以constructor也會被重新定義利赋,不再指向他的構(gòu)造函數(shù),所以可以自己寫一個constructor屬性指向他的構(gòu)造函數(shù)

原型鏈

每個構(gòu)造函數(shù)都有原型對象猩系,每個構(gòu)造函數(shù)實(shí)例都包含一個指向原型對象的內(nèi)部指針(proto)媚送,如果我們讓第一個構(gòu)造函數(shù)的原型對象等于第二個構(gòu)造函數(shù)的實(shí)例,結(jié)果第一個構(gòu)造函數(shù)的原型對象將包含一個指向第二個原型對象的指針寇甸,再然第三個原型對象等于第一個構(gòu)造函數(shù)的實(shí)例塘偎,這樣第三個原型對象也將包含指向第一個原型對象的指針疗涉,以此類推,就夠成了實(shí)例于原型的鏈條吟秩,這就是原型鏈的基本概念

function One(){

}

function Two(){

}

function Three(){

}

Two.prototype=new One();

Three.prototype=new Two();

var three=new Three();

console.log(three);

console.log(three.__proto__===Three.prototype) //true

console.log(three.__proto__.__proto__===Two.prototype) //true

console.log(three.__proto__.__proto__.__proto__===One.prototype)? //true

console.log(three.__proto__.__proto__.__proto__.__proto__===Object.prototype)? //true


在對象實(shí)例中博敬,訪問對象原型的方法

1、使用proto屬性

此屬性是瀏覽器支持的一個屬性峰尝,并不是ECMAScript里的屬性

2.Object.getPrototypeOf

3.使用constructor.prototype的方法

對于不支持proto的瀏覽器,可以使用constructor收恢,訪問到對象的構(gòu)造函數(shù)武学,在用prototype訪問到原型


使用原型鏈解釋ANUGLAR作用域

在開發(fā)過程中,我們可能會出現(xiàn)控制器的嵌套伦意,看下面這段代碼:

? ? <div ng-controller="OuterCtrl">

? ? ? ? <span>{{a}}</span>

? ? ? ? <div ng-controller="InnerCtrl">

? ? ? ? ? ? <span>{{a}}</span>

? ? ? ? </div>

? ? </div>

? ? <script>

? ? function OuterCtrl($scope) {

? ? $scope.a = 1;

? ? }

? ? function InnerCtrl($scope) {

? ? }

? ? </script>

我們可以看到界面顯示了兩個1火窒,而我們只在OuterCtrl的作用域里定義了a變量,但界面給我們的結(jié)果是驮肉,兩個a都有值,現(xiàn)在自控制器里的a是從父控制器里繼承過來的

我們可以父子級的作用域看成兩個原型對象熏矿,其中一個原型對象繼承另一個原型對象的實(shí)例

function Outer() {

? ? this.a = 1;

}

function Inner() {

}

var outer = new Outer();

Inner.prototype=new Outer();

var inner = new Inner();

console.log(outer.a)

console.log(inner.a)

Angular的實(shí)現(xiàn)機(jī)制其實(shí)也就是把這兩個控制器中的$scope作了關(guān)聯(lián),外層的作用域?qū)嵗蔀榱藘?nèi)層作用域的原型离钝。

既然作用域是通過原型來繼承的票编,自然也就可以推論出一些特征來。比如說這段代碼卵渴,點(diǎn)擊按鈕的結(jié)果是什么慧域?

<div ng-controller="OuterCtrl">

? ? <span>{{a}}</span>

? ? <div ng-controller="InnerCtrl">

? ? ? ? <span>{{a}}</span>

? ? ? ? <button ng-click="a=a+1">a++</button>

? ? </div>

</div>

<script>

function OuterCtrl($scope) {

? ? $scope.a = 1;

}

function InnerCtrl($scope) {

}

</script>

點(diǎn)了按鈕之后,兩個a不一致了浪读,里面的變了昔榴,外面的沒變,這是為什么碘橘?

function Outer() {

? ? this.a = 1;

}

function Inner() {

}

var outer = new Outer();

Inner.prototype=new Outer();

var inner = new Inner();

inner.a = inner.a + 1;

console.log(outer.a)

console.log(inner.a)

因?yàn)樵谠玩溨谢ザL問一個實(shí)例屬性時,會在實(shí)例本身查找痘拆,如果找不到仰禽,則搜索實(shí)例的原型,如果再搜索不到错负,則繼續(xù)沿著原型鏈往上查找坟瓢。找到之后則會賦給該實(shí)例踊兜,所以inner上面就被賦值了一個新的a纬乍,outer里面的仍然保持原樣,這也就導(dǎo)致了剛才看到的結(jié)果斤寂。

上下級共享變量

比如說识颊,我們就是想上下級共享變量诚镰,不創(chuàng)建新的奕坟,該怎么辦呢?

function Outer() {

? ? this.data = {

? ? ? ? a: 1

? ? };

}

function Inner() {

}

var outer = new Outer();

Inner.prototype = outer;

var inner = new Inner();

console.log(outer.data.a);

console.log(inner.data.a);

inner.data.a += 1;

console.log(outer.data.a);

console.log(inner.data.a);

我們可以把a(bǔ)寫在一個對象里清笨,當(dāng)inner找到對象data并賦值到自己身上時月杉,其實(shí)是復(fù)制了對象的指針(參考高程第4章復(fù)制引用類型和基本類型的區(qū)別),我們對對象里的屬性的改動都會反映到所有引用該對象的元素上抠艾。

反映到AngularJs,我們可以這么寫

<div ng-controller="OuterCtrl">

? ? <span>{{data.a}}</span>

? ? <div ng-controller="InnerCtrl">

? ? ? ? <span>{{data.a}}</span>

? ? ? ? <button ng-click="data.a=data.a+1">increase a</button>

? ? </div>

</div>

<script>

function OuterCtrl($scope) {

? ? $scope.data = {

? ? ? ? a: 1

? ? };

}

function InnerCtrl($scope) {

}

</script>

這樣點(diǎn)擊按鈕兩個控制器的a都會+1

---------------------


原文:https://blog.csdn.net/qq_42019025/article/details/80708446

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苛萎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子检号,更是在濱河造成了極大的恐慌腌歉,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齐苛,死亡現(xiàn)場離奇詭異翘盖,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)凹蜂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門馍驯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人玛痊,你說我怎么就攤上這事汰瘫。” “怎么了擂煞?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵吟吝,是天一觀的道長。 經(jīng)常有香客問我颈娜,道長剑逃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任官辽,我火速辦了婚禮蛹磺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘同仆。我一直安慰自己萤捆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布俗批。 她就那樣靜靜地躺著俗或,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岁忘。 梳的紋絲不亂的頭發(fā)上辛慰,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音干像,去河邊找鬼帅腌。 笑死驰弄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的速客。 我是一名探鬼主播戚篙,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼溺职!你這毒婦竟也來了岔擂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浪耘,失蹤者是張志新(化名)和其女友劉穎智亮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體点待,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年弃舒,在試婚紗的時候發(fā)現(xiàn)自己被綠了癞埠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡聋呢,死狀恐怖苗踪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情削锰,我是刑警寧澤通铲,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站器贩,受9級特大地震影響颅夺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛹稍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一吧黄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唆姐,春花似錦拗慨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至声功,卻和暖如春烦却,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背先巴。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工短绸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留车吹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓醋闭,卻偏偏與公主長得像窄驹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子证逻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

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