SoFunction
Updated on 2025-04-11

Scope Scope Learning Tutorial

What is scope?

Everyone knows that in AngularJS scope is an object pointing to the application model, and it is the execution environment for expressions. The scope has a hierarchy, and this level is almost the same as the corresponding DOM. Scope can monitor expressions and pass events.

In HTML code, once an ng-app directive is defined, a scope is generated. The scope generated by ng-app is quite special. It is a root scope ($rootScope), which is the top level of all other $Scopes.

In addition to using the ng-app directive to generate one scope, other directives such as ng-controller, ng-repeat, etc. will generate one or more scopes. In addition, you can also create a scope through the factory method of creating scopes provided by AngularJS. These scopes all have their own inheritance context and the root scope is $rootScope.

After generating a scope, when writing AngularJS code, the $scope object represents the data entity of this scope. We can define various data types in $scope, and then we can directly access the variable in HTML in {{variable name}}.

Inheritance scope

AngularJS retrieves the context when creating a scope. If there is already a scope in the context, the newly created scope will inherit the properties and methods of its parent scope using the JavaScript prototype inheritance mechanism.

Some AngularJS directives create new subscopes and perform prototype inheritance: ng-repeat, ng-include, ng-switch, ng-view, ng-controller,scope: true andtransclude: trueCreated directive.

The following HTML defines three scopes, namely the subscope created by $rootScope, parentCtrl and childCtrl created by the ng-app directive. The scope generated by childCtrl is also the subscope of parentCtrl.

Example 1: Inheritance instance of scope

<!doctype html>
<html>
<head>
 <meta charset=utf-8"/>
 <title>scope nick</title>
 <script src="/libs//1.4.6/"></script>
</head>
<script type="text/javascript">
 ('app', [])
  .controller('parentCtrl', ['$scope', function($scope) {
  $= 'Nick DeveloperWorks';
  }])
  .controller('childCtrl', ['$scope', function($scope) {
  $= 'Nick DeveloperWorks for test';
  }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
 <input ng-model="args">
 <div ng-controller="childCtrl">
 <input ng-model="args">
 </div>
</div>
</body>
</html>

The inheritance scope conforms to JavaScript's prototype inheritance mechanism, which means that if we access a property defined in a parent scope in the child scope, JavaScript first looks for the property in the child scope, and then searches from the parent scope on the prototype chain. If we have not found it, we will look for the parent scope of the previous level of the prototype chain. In AngularJS, the top of the scope prototype chain is $rootScope. AnguarJS will find $rootScope until it is found. If it still cannot be found, it will return undefined.

Let's use the example code to illustrate this mechanism. First, we explore the scope inheritance mechanism for prototype data types:

Example 2: Scope Inheritance Instance-primitive type data inheritance

<!doctype html>
<html>
<head>
 <meta charset=utf-8"/>
 <title>scope nick</title>
 <script src="/libs//1.4.6/"></script>
</head>
<script type="text/javascript">
 ('app', [])
  .controller('parentCtrl', ['$scope', function($scope) {
  $ = 'Nick DeveloperWorks';
  }])
  .controller('childCtrl', ['$scope', function($scope) {
  }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
 <input ng-model="args">
 <div ng-controller="childCtrl">
 <input ng-model="args">
 </div>
</div>
</body>
</html>

Test run results:

The first input box:

Although the specific args attribute is not defined in childCtrl, because the scope of childCtrl inherits from the scope of parentCtrl, AngularJS will find the args attribute in the parent scope and set it to the input box. And, if we change the content in the first input box, the content will be synchronized to the second input box.

The second input box:

The contents of the second input box will no longer be synchronized with the contents of the first input box. When changing the content of the second input box, because the model in the HTML code is explicitly bound to the scope of childCtrl, AngularJS will generate an args primitive type property for childCtrl. In this way, according to the AngularJS scope inheritance prototype mechanism, childCtrl can find the args attribute in its own scope, so it will no longer look for the args attribute of parentCtrl. From then on, the properties bound to the contents of the two input boxes are already two different instances, so they will no longer be kept in sync.

Now I am modifying the code as follows. Combining the above two scenarios, what will happen?

Example 3: Scope Inheritance Instance-Object Data Inheritance

<!doctype html>
<html>
<head>
 <meta charset=utf-8"/>
 <title>scope nick</title>
 <script src="/libs//1.4.6/"></script>
</head>
<script type="text/javascript">
 ('app', [])
  .controller('parentCtrl', ['$scope', function($scope) {
  $ = {};
  $ = 'Nick DeveloperWorks';
  }])
  .controller('childCtrl', ['$scope', function($scope) {
  }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
 <input ng-model="">
 <div ng-controller="childCtrl">
 <input ng-model="">
 </div>
</div>
</body>
</html>

The test result is that no matter the content of any input box is changed, the content of both is always synchronized.

According to the prototype inheritance mechanism of AngularJS, if ng-model binds object data, then AngularJS will not create an args object for childCtrl, and naturally there will not be any property. This way, the childCtrl scope will never exist Properties can only be found in the parent scope, that is, the changes in the two input boxes are actually just changing the parentCtrl scope. property. Therefore, the contents of both are always in sync.

Let’s look at another example to analyze the results.

Example 4: Scope Inheritance Instance - The data object of the parent scope is no longer accessed.

<!doctype html>
<html>
<head>
 <meta charset=utf-8"/>
 <title>scope nick</title>
 <script src="/libs//1.4.6/"></script>
</head>
<script type="text/javascript">
 ('app', [])
  .controller('parentCtrl', ['$scope', function($scope) {
  $ = {};
  $ = 'Nick DeveloperWorks';
  }])
  .controller('childCtrl', ['$scope', function($scope) {
  $ = {};
  $ = 'Nick DeveloperWorks for test';
  }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
 <input ng-model="">
 <div ng-controller="childCtrl">
 <input ng-model="">
 </div>
</div>
</body>
</html>

The test result is that the contents of the two input boxes will never be synchronized. If the child scope has an instance data object, the parent scope will not be accessed.

Independent scope

Independent scope is a very special scope in AngularJS, which only appears in directive. In the definition of directive, we add the previous onescope:{} attribute creates an isolation scope for this directive.

Example 5: Directive Create an orphan scope

('isolate', []).directive("isolate", function () {
 return {
 scope : {},
 };
})

The biggest feature of independent scope is that it will not inherit its parent scope and maintain relatively independent of the external parent scope. Therefore, if you want to access the properties of its parent scope in AngularJS directive that defines an orphan scope, the value you get is undefined. The code is as follows:

Example 6: Isolation in Independent Scope

&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
 &lt;meta charset=utf-8"/&gt;
 &lt;title&gt;scope nick&lt;/title&gt;
 &lt;script src="/libs//1.4.6/"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;script type="text/javascript"&gt;
 ('app', [])
  .controller('ctrl', ['$scope', function($scope) {
  $ = {};
  }])
  .directive("isolateDirective", function () {
  return {
   scope : {},
   link : function($scope, $element, $attr) {
   ($scope.$args); //Output undefined   }
  };
  });
&lt;/script&gt;
&lt;body ng-app="app"&gt;
&lt;div ng-controller="ctrl"&gt;
 &lt;div isolate-directive&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

In the above code, a scope is created by declaring the scope property in directive, whose parent scope is the scope to which ctrl belongs. However, this scope is orphaned, so it does not access any properties in the parent scope. The advantage of such a design mechanism is that it is possible to create columns of reusable directives that do not cause crosstalk to each other on the property values ​​they have, nor do they have any side effects.

AngularJS independent scoped data binding

In inheritance scope, we can choose the child scope to directly operate the parent scope data to realize the communication between the parent and child scope, while in the independent scope, the child scope cannot directly access and modify the properties and values ​​of the parent scope. In order to enable orphan scopes to communicate with the outside world, AngularJS provides three ways to break the limitation of "isolated" of independent scopes.

One-way binding (@ or @attr)

This is the simplest type of data communication between AngularJS independent scope and external parent scope. The bound object can only be the string value in the parent scope, and is a one-way read-only reference. The string value in the parent scope cannot be modified. In addition, this string must also be declared as an attr (attribute) in the HTML node of the parent scope.

When using this binding method, you need to explicitly specify the HTML string attribute in the parent scope in the scope property of the directive, otherwise an exception will be thrown. The sample code is as follows:

Example 7: One-way binding example

&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
 &lt;meta charset=utf-8"/&gt;
 &lt;title&gt;scope nick&lt;/title&gt;
 &lt;script src="/libs//1.4.6/"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;script&gt;
 ('isolateScope', [])
  .directive("isolateDirective", function () {
  return {
   replace : true,
   template: '&lt;button&gt;{{isolates}}&lt;/button&gt;',
   scope : {
   isolates : '@',
   },
   link : function($scope, $element, $attr) {
   $ = "DeveloperWorks";//invalid   }
  };
  })
  .controller("ctrl", function ($scope) {
  $ = 'NICK';
  });
&lt;/script&gt;
&lt;body ng-app="isolateScope" &gt;
&lt;div ng-controller="ctrl"&gt;
 &lt;button&gt;{{btns}}&lt;/button&gt;
 &lt;div isolate-directive isolates="{{btns}}"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

The above code is declared in directivescope:{isolates:'@'}Make directive have the value owned by the HTML attribute data-isolates (isolates is a custom property in the parent scope. It is OK to not add data, but it is recommended to add data) in the controller ctrl. This value is assigned to 'nick'. So, the result of the code running is that there are two buttons called nick on the page.

We also noticed that isolates is modified in the link function, but it will not be reflected in the run result in the end. This is because isolates is always bound to the btns string in the parent scope. If the btns in the parent scope does not change, then no matter how isolates is modified in the orphan scope, it will not work.

With this form of binding, the orphan scope will have the ability to access the function objects in the parent scope, so that the functions in the parent scope can be executed to obtain certain results. This method of binding is the same as one-way binding. It can only access the parent function in a read-only manner, and the definition of this function must be written on the attr (attribute) node in the parent scope HTML.

Although this binding cannot modify the function object set by attr in the parent scope, it can be used to execute functions to change the values ​​of certain attributes in the parent scope to achieve some expected effects. The sample code is as follows:

Example 8: Reference binding example

<!doctype html>
<html>
<head>
 <meta charset=utf-8"/>
 <title>scope nick</title>
 <script src="/libs//1.4.6/"></script>
</head>
<script>
 ('isolateScope', [])
   .directive("isolateDirective", function () {
    return {
     replace : true,
     scope : {
      isolates : '&',
     },
     link : function($scope, $element, $attr) {
      var func = $();
      func();
     }
    };
   })
   .controller("ctrl", function ($scope) {
    $ = function () {
     ("Nick DeveloperWorks");
    }
   });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
 <div isolate-directive data-isolates="func"></div>
</div>
</body>
</html>

In this example, the browser's console will print the text "Nick DeveloperWorks".

In the above code, we specify a function object in the parent scope.$, refers to func through binding to HTML attributes in orphan scope. It should be noted that the use of func objects in the link function.$ What we get is a function object, not a call to this object, so we need to finish calling it$ Only by calling this function later can you get the real execution result.

Bidirectional binding (=or =attr)

Bidirectional binding gives AngularJS the most freest bidirectional data communication function to the outside world. In bidirectional binding mode, orphan scopes can directly read and write properties and data in the parent scope. Like the above two orphan scope definition data binding, two-way binding must also be set in the HTML of the parent scope to bind.

Bidirectional binding is very suitable for some scenarios where child directives require frequent data interaction with the parent scope and the data is relatively complex. However, since you can freely read and write properties and objects in the parent scope, you need to be careful when using multiple directives in some scenarios where parent scope data is shared, which can easily cause confusion on the data.

The sample code is as follows:

Example 9: Bidirectional binding example

<!doctype html>
<html>
<head>
 <meta charset=utf-8"/>
 <title>scope nick</title>
 <script src="/libs//1.4.6/"></script>
</head>
<script>
 ('isolateScope', [])
   .directive("isolateDirective", function () {
    return {
     replace : true,
     template: '<button>{{isolates}}</button>',
     scope : {
      isolates : '=',
     },
     link : function($scope, $element, $attr) {
      $ = "NICK";
     }
    };
   })
   .controller("ctrl", function ($scope) {
    $ = {
     name : 'nick',
     dw : 'DeveloperWorks'
    };
   });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
 <button>{{}}</button>
 <button>{{}}</button>
 <div isolate-directive data-isolates="btns"></div>
</div>
</body>
</html>

The result of the above code running is that there are three buttons appearing on the browser page, with the first button titled "DeveloperWorks" and the second and third button titled "NICK".

Initially in parent scope$In lowercase "nick", through two-way binding, the parent scope's name is rewritten into uppercase "NICK" in orphan scope and takes effect directly, and the parent scope's value is changed.

Summarize

The above is the entire content of this article. I hope the content of this article will be of some help to your study or work. If you have any questions, you can leave a message to communicate. Thank you for your support.