Angular.JS中Scope繼承的示例分析-創(chuàng)新互聯(lián)

這篇文章主要介紹Angular.JS中Scope繼承的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、成都做網(wǎng)站、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、景德鎮(zhèn)ssl等。為1000多家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的景德鎮(zhèn)網(wǎng)站制作公司

基本原理

在JavaScript中,每創(chuàng)建一個(gè)構(gòu)造函數(shù)(constructor),就會(huì)同時(shí)給該函數(shù)生成一個(gè)指向原型對(duì)象的屬性prototype。每個(gè)原型對(duì)象又獲得一個(gè)constructor屬性指向相應(yīng)的構(gòu)造函數(shù),原型對(duì)象的其他屬性和方法從Object繼承而來(lái)。每個(gè)通過(guò)構(gòu)造函數(shù)創(chuàng)建的實(shí)例,都包含一個(gè)指向構(gòu)造函數(shù)原型對(duì)象的內(nèi)部屬性[[Prototype]](在瀏覽器中通常實(shí)現(xiàn)為_(kāi)_proto__)。構(gòu)造函數(shù)、原型對(duì)象和實(shí)例三者的關(guān)系如下 (圖片來(lái)源:《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》):

Angular.JS中Scope繼承的示例分析

person1和person2為構(gòu)造函數(shù)Person創(chuàng)建的兩個(gè)實(shí)例,可以通過(guò)[[Prototype]]屬性訪問(wèn)原型對(duì)象Person Prototype,獲得原型中定義的所有方法和屬性。Person構(gòu)造函數(shù)的prototype屬性同樣指向Person Prototype原型對(duì)象。以上這些概念是理解原型繼承的基礎(chǔ),下面我們來(lái)看原型鏈的概念。如果把一個(gè)類型的實(shí)例賦值給一個(gè)原型對(duì)象會(huì)發(fā)生什么?根據(jù)上圖中的關(guān)系,此時(shí)的原型對(duì)象包含指向另一個(gè)原型的屬性,而另一個(gè)原型中也包含著指向另一個(gè)構(gòu)造函數(shù)的屬性。

效果如下圖:

Angular.JS中Scope繼承的示例分析

SuperType為一個(gè)父類型,在原型中定義了屬性property和方法getSuperValue;SubType是一個(gè)子類型,定義了屬性subproperty和方法getSubValue。instance為SubType的一個(gè)實(shí)例。這里通過(guò)下面的關(guān)鍵代碼,將SubType的原型對(duì)象變?yōu)镾uperType對(duì)象的實(shí)例:

SubType.prototype = new SuperType(); 
SubType.prototype.getSubValue = function(){ 
 return this.subproperty; 
};

我們看到,SubType的原型對(duì)象中有來(lái)自SuperType實(shí)例對(duì)象的property屬性,以及自己在原型上定義的getSubValue方法,通過(guò)[[Prototype]]屬性,又可以進(jìn)一步訪問(wèn)SuperType原型對(duì)象中的成員。假如SuperType的原型也被賦值成某個(gè)類型的實(shí)例,依次類推,那么可以通過(guò)[[Prototype]]屬性一直向上回溯,形成一條直通Object原型對(duì)象的原型鏈。上面的例子只展示了鏈條的前兩環(huán)。

通過(guò)原型鏈的實(shí)現(xiàn),SubType的實(shí)例繼承了SuperType實(shí)例的的所有實(shí)例成員和原型成員。例如,若要訪問(wèn)instance.getSuperValue,首先在instance實(shí)例內(nèi)部搜索,沒(méi)有該方法;然后通過(guò)原型鏈向上回溯,找到SubType原型對(duì)象,也沒(méi)有該方法;再通過(guò)[[Prototype]]屬性繼續(xù)回溯,來(lái)到SuperType的原型對(duì)象,找到該方法。

以上描述的這種繼承方式就是原型繼承。在ES5以后,可以使用Object提供的create方法規(guī)范化上述過(guò)程,詳細(xì)請(qǐng)參考這里。AngularJS的Scope繼承關(guān)系的實(shí)現(xiàn)類似上述過(guò)程。

Scope繼承實(shí)現(xiàn)

在Angular中,想要定義一個(gè)Scope的child Scope可以通過(guò)scope.$new方法實(shí)現(xiàn),而$new方法本身的實(shí)現(xiàn)就體現(xiàn)了上述原型繼承的思想。首先,$new方法接受兩個(gè)參數(shù):isolated和parent。第一個(gè)參數(shù)表示創(chuàng)建的child scope是否是一個(gè)隔離的(isolated)。隔離的scope不繼承parent scope的原型,只是在層次結(jié)構(gòu)(hierachy)上屬于其child scope,這種結(jié)構(gòu)是Digest過(guò)程的基礎(chǔ)。isolated scope的一個(gè)好處是避免parent scope的成員被更改,在directive的實(shí)現(xiàn)里很有用。第二個(gè)參數(shù)指定創(chuàng)建的child scope的parent scope,如果不指定,默認(rèn)為當(dāng)前調(diào)用$new方法的scope。Angular中$new的實(shí)現(xiàn)類似:

$new : function(isolate, parent) { 
  var child; 
  parent = parent || this; 
  if (isolate) { 
   child = new Scope(); 
   child.$root = this.$root; 
  } else { 
   if (!this.$$ChildScope) { 
   this.$$ChildScope = createChildScopeClass(this); 
   } 
   child = new this.$$ChildScope(); 
  } 
  child.$parent = parent; 
  //... 
  return child; 
},//...

可以看出,如果是isolate為true,則使用Scope類型構(gòu)造函數(shù)創(chuàng)建一個(gè)child對(duì)象。如果isolate為false或者未指定,則創(chuàng)建一個(gè)child scope原型繼承于當(dāng)前scope,這個(gè)過(guò)程由createChildScopeClass提供的構(gòu)造函數(shù)實(shí)現(xiàn):

function createChildScopeClass(parent) { 
 function ChildScope() { 
  this.$$watchers = null; 
  this.$$listeners = {};//... 
 } 
 ChildScope.prototype = parent; 
 return ChildScope; 
 }

這里定義了ChildScope類型,包括其需要的屬性。然后將該類型的prototye屬性設(shè)置為傳入的scope實(shí)例(即前面的this),這就是前面闡述的原型繼承。之后通過(guò)ChildScope創(chuàng)建的scope對(duì)象都是原型繼承于parent的,即可以訪問(wèn)parent scope的所有成員。結(jié)合$new的代碼,如果child非隔離,則child可以訪問(wèn)當(dāng)前scope對(duì)象中的所有成員(例如$digest,$apply等方法以及自定義成員)。這就解釋了在我們自己創(chuàng)建的controller對(duì)應(yīng)的scope里,可以訪問(wèn)$rootScope提供的成員,因?yàn)槲覀兊膕cope最終原型繼承自root scope,因而可以通過(guò)原型鏈向上回溯到root scope的實(shí)例。

在前面一篇文章中,談到了Angular中Digest過(guò)程。當(dāng)調(diào)用scope.$apply方法時(shí),實(shí)際上是從root scope開(kāi)始,按照scope的層次結(jié)構(gòu),調(diào)用每個(gè)scope的$digest方法。這就是為什么在Scope的構(gòu)造函數(shù)中會(huì)設(shè)置$root屬性:

function Scope() { 
  this.$parent = null;//... 
  this.$root = this; 
  this.$$destroyed = false; 
  this.$$listeners = {}; 
  //... 
}

對(duì)于一般child scope,$root會(huì)通過(guò)原型繼承得到,在root scope構(gòu)造以后,后續(xù)的scope都可以訪問(wèn)$root對(duì)象,即是root scope對(duì)象。對(duì)于isolated scope,由于是通過(guò)Scope構(gòu)造函數(shù)創(chuàng)建(非原型繼承),$root被child scope覆蓋,需要將$root屬性設(shè)置為parent的$root屬性,如前面$new的實(shí)現(xiàn)。這就保證了在任何一個(gè)scope中始終能拿到root scope的實(shí)例,也就可以完成自上而下的Digest過(guò)程,在$apply等方法的實(shí)現(xiàn)中,使用$rootScope代替$root,二者相同:

$apply: function(expr) { 
  beginPhase('$apply'); 
  try { 
   return this.$eval(expr); 
  } finally { 
   clearPhase(); 
  } 
  finally { 
   $rootScope.$digest(); 
  } 
},//...

$rootScope是$RootScopeProvider提供的Scope類型實(shí)例,是最先初始化的scope對(duì)象。在開(kāi)發(fā)中,我們可以這樣使用child scope:

.controller('smallCatCtrl', [ 
 '$scope', function($scope){ 
    
  var child = $scope.$new(); 
  child.text = 'cat'; 
   
  var child1 = $scope.$new(true); 
  child1.value = 0; 
   
   var child2 = $scope.$new(true, child); 
   child2.value = 1; 
   
  child2.$watch('value', function(oldValue, newValue){ 
   console.log('child2.value changed'); 
  }); 
  child1.$watch('value', function(oldValue, newValue){ 
   console.log('child1.value changed'); 
  }) 
  child.$watch('text', function(oldValue, newValue){ 
   console.log('child.text changed'); 
  }); 
  console.log(child2.text); 
 
 }]);

在這段代碼中,首先創(chuàng)建$scope的一個(gè)子scope----child,沒(méi)有給$new指定參數(shù),意味著child原型繼承于$scope。同時(shí)定義了child的屬性text。接下來(lái)創(chuàng)建$scope的第二個(gè)子scope----child1,傳入$new的參數(shù)要求child1是isolated scope,并且在層次結(jié)構(gòu)上是$scope的后代。同時(shí)定義了其value屬性。最后創(chuàng)建scope child2,它也是一個(gè)isolated scope,不同的是它以child為層次結(jié)構(gòu)上的parent scope。

這段代碼的輸出如下:

Angular.JS中Scope繼承的示例分析

首先,child2只是在層次結(jié)構(gòu)上繼承于child,因此沒(méi)有把child實(shí)例作為原型,也就沒(méi)有text屬性,第一行輸出undefined。
由于Digest過(guò)程按scope層次結(jié)構(gòu)自上而下進(jìn)行,類似于樹(shù)的深度遍歷過(guò)程。在該例中scope的順序?yàn)?scope->child->child2->child1,因此三個(gè)watch listener函數(shù)的輸出也按照上面的順序。

以上是“Angular.JS中Scope繼承的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站muchs.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

本文標(biāo)題:Angular.JS中Scope繼承的示例分析-創(chuàng)新互聯(lián)
當(dāng)前URL:http://muchs.cn/article34/diedpe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、建站公司營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、網(wǎng)站排名、響應(yīng)式網(wǎng)站網(wǎng)站營(yíng)銷(xiāo)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站