摘要:原文發自我的博客易企秀招聘啦首先我們先來回顧以下中出現的原型繼承原型繼承自如果我們要在上查詢一個定義在的屬性會先在上查找如果沒有查到那么會順著原型鏈去查找所以以下判別式均為如果我們做如下操作原型鏈并沒有被訪問一個新的會被加入到的屬性中去新的
原文發自我的博客 xiaoyu2er.github.io
易企秀招聘啦!
JavaScript Prototypal Inheritance首先我們先來回顧以下 javascript 中出現的原型繼承:
function ParentScope(){ this.aString = "parent string"; this.aNumber = 100; this.anArray = [10,20,30]; this.anObject = { "property1": "parent prop1", "property2": "parent prop2" }; this.aFunction = function(){ return "parent output"; } } function ChildScope(){ } ChildScope.prototype = new ParentScope(); var childScope = new ChildScope();
ChildScope 原型繼承自 ParentScope
如果我們要在 childScope 上查詢一個定義在 parentScope 的屬性, JavaScript 會先在 childScope 上查找, 如果沒有查到, 那么會順著原型鏈去查找. 所以以下判別式均為 true
childScope.aString === "parent string" childScope.anArray[1] === 20 childScope.anObject.property1 === "parent prop1" childScope.aFunction() === "parent output"
如果我們做如下操作:
childScope.aString = "child string"
原型鏈并沒有被訪問, 一個新的 aString 會被加入到 childScope 的屬性中去, 新的屬性會隱藏 parentScope 中的同名屬性.
假設我們做出如下操作:
childScope.anArray[1] = 22 childScope.anObject.property1 = "child prop1"
原型鏈被訪問了. 因為 anArray, anObject 沒有在 childScope 中找到.
新的賦值操作均在 parentScope 上進行. childScope 上沒有添加任何新的屬性.
如果我們做出如下操作
childScope.anArray = [100, 555] childScope.anObject = { name: "Mark", country: "USA" }
原型鏈沒有被訪問, childScope 會獲得兩個新的屬性, 并且會隱藏 parentScope 上的同名屬性.
仔細體會上面的三次操作. 第一第三次均是對某個屬性進行賦值, 原型鏈并不會被訪問, 由于屬性并不存在, 所以新的屬性將會被添加. 而第二次其實是先訪問, childScope.anArray, childScope.anObject, 再對其訪問的對象的某個屬性進行復制.
總結:
如果我們讀取 childScope.propertyX, 而 childScope 擁有 propertyX, 那么原型鏈不會被訪問
如果我們讀取 childScope.propertyX, 而 childScope 并沒有 propertyX, 那么原型鏈會被訪問.
如果對 childScope.propertyX 進行賦值, 那么原型鏈并不會被訪問.
最后我們再來看一種情況:
delete childScope.anArray childScope.anArray[1] === 22 // true
我們顯示刪除了 childScope 的一個屬性, 接著試圖讀取這個屬性, 由于 childScope 并沒有了這個屬性, 所以原型鏈會被訪問.
Angular Scope Inheritance接著我們來看看 Angular 中的 scope 繼承
以下指令會創建新的 scope, 并且會在原型上繼承 父scope (即$scope.$parent, 下文兩個詞互為同義詞):
ng-repeat
ng-switch
ng-view
ng-controller
帶有 scope: true 的指令
帶有 transclude: true 的指令
以下指令創建新的指令, 且在原型上 不繼承 父scope:
帶有 scope: { ... } 的指令, 這會創建一個 獨立的scope (isolate scope)
注意: 默認指令并不會創建 scope, 默認是 scope: false, 通常稱之為 共享scope.
讓我們來看幾個例子:
ng-includeJS:
$scope.myPrimitive = 50; $scope.myObject = {aNumber: 11};
HTML:
{{ myPrimitive }}
{{ myObject.aNumber }}
每一個 ng-include 都會創建一個 子scope, 并在原型上繼承 父 scope
向第一個 input 輸入數字, 一個新的屬性 myPrimitive 將會被創建, 同時隱藏 父 scope 的 myPrimitive;
向第二個 input 輸入數字, 子 scope 并不會創建一個新的屬性, 這時候原型繼承發揮了作用.
第一種情況很可能不是我們期待的結果, 所以可以顯式的調用 $parent 來解決這個問題.
向第一個 input 鍵入數字, 這時候就不會產生新的屬性了. $parent 指向了 父scope. 但是 $parent 和 原型上的繼承并不一定相等. 稍后我們會看到一個例子.
對于所有的 scope, 無論是共享的(scope: false), 繼承的(scope: true), 還是孤立的(scope: { ... }), Angular 都會建立一個 父-子 的層級關系, 這個層級關系是根據 dom 結構的層級關系決定的, 可以通過
$parent $$childHead $$childTail
來訪問.
為了避免剛才的例子出現的子 scope 創建新屬性情況的發聲, 除了使用 $scope, 還可以使用調用原型鏈上的方法.
// in the parent scope $scope.setMyPrimitive = function(value) { $scope.myPrimitive = value; }ng-switch ng-view
ng-switch, ng-view 與 ng-include 情況類似, 不贅述.
ng-repeatng-repeat 有一點特殊.
JS:
$scope.myArrayOfPrimitives = [ 11, 22 ]; $scope.myArrayOfObjects = [{num: 101}, {num: 202}]
HTML:
對于每一次迭代, ng-repeat 都會創建一個 子scope, 并在原型上繼承 父scope, 但是他還會將 父scope 上的屬性賦值到 子scope 上. 新的屬性名就是 ng-repeat="** in parentScope.property" 中的 **.
源碼中的 ng-repeat 是這樣的:
childScope = scope.$new(); // child scope prototypically inherits from parent scope ... childScope[valueIdent] = value; // creates a new childScope property
如果 ** 是 primitive, 那么一份 copy 會被賦值到新的屬性上. 修改 子scope 上的新屬性自然不會修改 父 scope 上的屬性.
如果 ** 是個 object, 那么一個 reference 會被賦值到新的 子scope 屬性上. 修改這個屬性, 就是修改 父scope 對應的屬性.
ng-controllerng-controller 也是會創建新的 子scope, 同時原型繼承 父scope. 如同 ng-include, ng-switch, ng-view.
但是, 使用 $scope 來共享數據被認為是一種不好的操作. 因為原型鏈可是會一直向上追溯的.
如果想要共享數據, 最好使用 service.
我們來總結以下指令中的 scope:
scope: false(默認的), 指令不會創建新的 scope, 沒有繼承關系. 與 $parent 共享 $scope.
scope: true, 指令會創建一個 子scope, 并在原型上繼承 $parent. 如果在一個 DOM 上有多個指令想要創建新的 scope, 會報錯.
scope: { ... }, 指令會創建一個 孤立的scope. 這在創建可重用的組件時是最好的選擇. 但是, 即使如此, 指令還是希望讀取 $parent 的數據. 這個時候可以使用如下符號獲得:
scope: { **: "="} 與 $parent 建立雙向綁定.
scope: { **: "@"} 與 $parent 建立單向綁定.
scope: { **: "&"} 綁定 $parent 的表達式.
想要獲得相應的屬性, 必須通過指令上的屬性獲得
HTML: JS: scope: { localProp: "@theParentProp" } HTML: JS: scope: { interpolatedProp: "@interpolated", twowayBindingProp: "=twowayBinding" } 指令在 link 期間: scope.someIsolateProp = "I"m isolated" transclude: true, 指令創建了一個 "transcluded" 的子scope, 在原型上繼承其 父scope. 如果上述例子同時具有transclude: true. 那么這個 "transcluded" scope, 和 "islolated" scope 是姊妹關系. 他們的 $parent 指向同一個 scope. 且 isolate scope 的 $$nextSibling 就是這個 "transcluded scope". 下圖反應了他們之間的關系: Angular Wiki: Understanding Scopes 文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。 轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78566.html
假設:
其中的關系如圖:
摘要:如何在中使用動畫前端掘金本文講一下中動畫應用的部分。與的快速入門指南推薦前端掘金是非常棒的框架,能夠創建功能強大,動態功能的。自發布以來,已經廣泛應用于開發中。 如何在 Angular 中使用動畫 - 前端 - 掘金本文講一下Angular中動畫應用的部分。 首先,Angular本生不提供動畫機制,需要在項目中加入Angular插件模塊ngAnimate才能完成Angular的動畫機制...
摘要:錯過了一周的優質內容,不要再錯過周一的快速回顧一周深度揭秘啟動全過程翻譯組每周社區問答入門語言簡明入門與提高一只爬蟲崔小拽爬蟲知乎用戶數據爬取和分析如何學習開源動效分析二動畫最佳實踐一工具箱之生命周期工具箱之權限管理一步步創建自己的框 錯過了一周的優質內容,不要再錯過周一的快速回顧 一周 fir.im Weekly -《深度揭秘 App 啟動全過程》 SwiftGG翻譯組 -《每周 S...
摘要:錯過了一周的優質內容,不要再錯過周一的快速回顧一周深度揭秘啟動全過程翻譯組每周社區問答入門語言簡明入門與提高一只爬蟲崔小拽爬蟲知乎用戶數據爬取和分析如何學習開源動效分析二動畫最佳實踐一工具箱之生命周期工具箱之權限管理一步步創建自己的框 錯過了一周的優質內容,不要再錯過周一的快速回顧 一周 fir.im Weekly -《深度揭秘 App 啟動全過程》 SwiftGG翻譯組 -《每周 S...
閱讀 1537·2021-11-24 10:17
閱讀 1031·2021-09-29 09:43
閱讀 2165·2021-09-23 11:21
閱讀 2161·2019-08-30 14:13
閱讀 1295·2019-08-29 13:58
閱讀 3157·2019-08-28 17:51
閱讀 1803·2019-08-26 13:29
閱讀 2973·2019-08-26 10:13