JavaScript プロトタイプ継承の概要
AngularJs には双方向のデータ バインディングがありますが、すべての変更が対応する効果を生み出すわけではありません。これは、基本型の値が渡されたときに発生することがあります。この状況は JavaScript 自体にも存在するはずです。まずは穴を掘って、JavaScript をしっかり学んでから埋めていきます。
上の図はJavaScriptのプロトタイプ継承図で、サブクラスが親クラスの属性を継承する際に、プロトタイプチェーンにアクセスします。つまり、親クラスでプロパティが見つかるまで、レイヤーごとに進みます。ただし、サブクラスの基本型のプロパティに値を直接割り当てると、プロトタイプ チェーンにはアクセスできません。つまり、同じ名前の新しいプロパティがサブクラスに作成され、親のプロパティが作成されます。再度アクセスしてもクラスにはアクセスされません。親クラスから継承したオブジェクトにアクセスする場合は、プロトタイプ チェーンにアクセスします。
childScope.aString === 'parent string' //true 访问了原型链 childScope.aNumber === 100 //true 访问了原型链 childScope.aNumber = 20 //不访问原型链,子类中将增加一个新属性,值为20 childScope.aString = 'child string' //不访问原型链,子类中将增加一个新的属性,值为 child string childScope.anArray[2] = 100 //访问了原型链,父类中的anArray对象中第三个值被修改
AngularJS で ng-repeat、ng-switch、ng-include をテストする
<!DOCTYPE html> <html ng-app="TestScopeModule"> <head> <script src="**/angular.js"></script> <script src="scopeTest.js"></script> <script type="text/ng-template" id="login"> <button ng-click="login()">login</button> <input type="checkbox" ng-model="loginData"/> <a href="#" ng-click="showScope($event)">switch's child scope,ng-include scope</a> </script> <script type="text/ng-template" id="logout"> <button ng-click="logout()">logout</button> <input type="checkbox" ng-model="loginData"/> <a href="#" ng-click="showScope($event)">switch's child scope,ng-include scope</a> </script> <script type="text/ng-template" id="login1"> <button ng-click="login1()">login</button> <input type="checkbox" ng-model="parent.loginData"/> <a href="#" ng-click="showScope($event)">switch's child scope,ng-include scope</a> </script> <script type="text/ng-template" id="logout1"> <button ng-click="logout1()">logout</button> <input type="checkbox" ng-model="parent.loginData"/> <a href="#" ng-click="showScope($event)">switch's child scope,ng-include scope</a> </script> </head> <body> <div ng-controller="TestScopeCtrl"> <div ng-repeat="item in list1"> <label>Input {{$index+1}}</label> <input type="text" ng-model="item"/> <a href="#" ng-click="showScope($event)">parent scope's child scope</a> </div> <div> {{list1}} </div> <hr/><hr/> <div ng-repeat="item in list2"> <label>input{{$index+1}}</label> <input type="text" ng-model="item.text"/> <a href="#" ng-click="showScope($event)">parent scope's child scope</a> </div> <div> {{list2}} </div> <hr/><hr/> <div> <a href="#" ng-click="showScope($event)">parent scope</a> </div> <hr/><hr/> <div ng-switch on="loginData"> <div ng-switch-when="false"><a href="#" ng-click="showScope($event)">switch's parent scope, parent scope's child scope</a><div ng-include="'login'"></div></div> <div ng-switch-when="true"> <a href="#" ng-click="showScope($event)">switch's parent scope, parent scope's child scope, different with false case</a> <div ng-include="'logout'"> </div> <a href="#" ng-click="showScope($event)">parent scope, not switch scope</a> </div> <hr/><hr/> <div ng-switch on="parent.loginData"> <div ng-switch-when="false"><a href="#" ng-click="showScope($event)">switch's parent scope, parent scope's child scope</a><div ng-include="'login1'"></div></div> <div ng-switch-when="true"> <a href="#" ng-click="showScope($event)">switch's parent scope, parent scope's child scope, different with false case</a> <div ng-include="'logout1'"> </div> </div> </div> </body> </html>
var TestScopeModule = angular.module('TestScopeModule', []); TestScopeModule.controller('TestScopeCtrl',['$scope',function ($scope) { $scope.list1 = ['value1','value2', 'value3']; $scope.list2 = [{text : 'value1'},{text : 'value2'},{text : 'value3'}]; $scope.showScope = function (e) { console.log(angular.element(e.srcElement).scope()); }; $scope.loginData = false; $scope.parent = {}; $scope.parent.loginData = false; $scope.login = function () { $scope.loginData = true; }; $scope.logout = function () { $scope.loginData = false; }; $scope.login1 = function () { $scope.parent.loginData = true; }; $scope.logout1 = function () { $scope.parent.loginData = false; }; }])
上記は、ng-repeat、ng-switch、ng-include をそれぞれテストする小さなテスト コードです。テスト結果はマークされています。コード内では、子スコープと親スコープのスコープです。
親スコープの属性と値
最初のng-repeatの最初の子スコープ、スコープは独自の項目属性と値を持ちます、ここでは基本的なデータ型であるためです、値を変更するときにプロトタイプ チェーンにはアクセスしないため、親スコープの値とは異なります。 ng-repeat は複数の子スコープを生成し、各子スコープは独自の item 属性を持ちます。
2 番目の ng-repeat の最初の子スコープには、スコープ内に独自の項目属性と値があります。ここでの項目はオブジェクトなので、項目オブジェクトの値を変更すると、プロトタイプ チェーンは次のようになります。 ngswitch が生成する子スコープでは、$parent が親スコープであることがわかります。ここでは ngswitch で nginclude を使用しているため、nginclude も独自のスコープを生成するため、childHead と childTail が存在します。 ngswitch は、true と false の場合にそれぞれスコープを生成します。これは、異なる ID 番号を持つ 2 つの異なるスコープです。
これは、ngswitch の nginclude によって生成された子スコープです。$parent の $id が 12 であり、ngswitch によって生成されたスコープの ID であることがわかります。