Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Jim Priest
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Jim Priest@thecrumb )

When To Use $scope vs. scope In AngularJS

By Ben Nadel on

When I first got into AngularJS, I started using the variable reference, "$scope," everywhere that an AngularJS scope was available. I've kept this practice up for the last two years. Then, a week or so ago, Jonathan Rowny pointed out that I was using "$scope" inappropriately in certain circumstances. As such, I'm implementing a change in my naming conventions.

Rowny pointed out that the "$" in "$scope" indicates that the scope value is being injected into the current context. But, not all references to scope are based on dependency injection. For example, in $watch, link, and cloning functions (not an exhaustive list), scope is always passed as a positional argument, regardless of its name. As such, it shouldn't be prefixed with "$".

So, going forward, my non-dependency-injection functions will go from this:

  • function link( $scope, element, attributes ) {
  •  
  • // ... with "$"
  •  
  • }

... to this:

  • function link( scope, element, attributes ) {
  •  
  • // ... without "$"
  •  
  • }

I know this might seem very nit-picky; but, I like to be mindful of the code - it makes me happy.




Reader Comments

Thanks, Ben!

I too like to be "mindful of the code" so this post interests me. I am, however, rather new to AngularJS and wondered if you could give a contextual code example of when it would be proper to use `scope` vs. `$scope`? I am just not informed well enough to understand what you mean when you say a scope reference may not be "based on dependency injection."

Thanks again,
Jim

Reply to this Comment

@Jim,

No problem. When the arguments are passed-in via dependency injection, their position (in the list of arguments) doesn't matter. So, for example, I could define a Controller like this:

app.controller( "MyController", function( $scope, $timeout, $http ) { .. } );

... (scope-first) or like this:

app.controller( "MyController", function( $timeout, $http, $scope ) { .. } );

... (scope last) and it won't make a difference. This is because AngularJS doesn't care about the order of the arguments, only their names. It then uses the argument name to pull something out of the dependency-injection container and use it during invocation.

For other methods, like the link() function, that accept scope, the position is *important* and the name is irrelevant. Meaning, you could define your link function like:

function link( scope, element, attributes ) { ... }

... or like:

function link( FOO, BAR, BAZ ) { ... }

In the latter case, Foo=scope, Bar=element, Baz=attributes. This is because AngularJS doesn't care what *you* name those variables, it only cares about the position in the list (ie, Scope:0, Element:1, Attributes:2, Controller:3, Transclude:4).

Controllers, Services, Factories, and Directive functions all use dependency injection. But, off the top of my head, the following functions do *not* use DI, only positional arguments (one of which is scope).

// Linking functions (and probably other pre-link functions).
function link( scope ) { ... }

// Watch expressions (not handlers).
$scope.$on( function watchExpression( scope ) { ... }, .... )

// Transclude clone functions.
transclude( function linkClonedNode( clone, scope ) { ... } )

I hope that helps a bit.

Reply to this Comment

@Ben,

Thanks, that helps! I haven't had as much need for the non DI stuff in my current experimentation so I hadn't seen a lot of what you were talking about.

I appreciate your writing on this site--I learn a lot!

Reply to this Comment

@Jim,

No problem. Most of the non-DI scope usage seems to be inside of Directives; so, if you're just getting into AngularJS, and use the native directives, you'll probably be using "$scope" most of the time.

Hit me up if you have any AngularJS questions - I love it.

Reply to this Comment

Hi Ben, like Jim that contextual example really helps me better understand the differences. I tend to just put $scope everywhere I need a binding to the view. Not ideal, but still early days for me.

Reply to this Comment

@Pete,

The only different is mindset, I suppose. A variable name is a variable name is a variable name. As such, using "$scope" everywhere won't have any negative impact on the script. For me, I just realized that using it uniformly was a symptom of my own incomplete mental model.

So, I guess it's just personal preference.

Reply to this Comment

Is there any analogy for $scope and scope in Java. I am new to AngularJS, and I want to get clear ideas about the difference between them.

Reply to this Comment

@Jaasir,

Do you mean "JavaScript" (instead of "Java")? Maybe I am not sure what you are asking.

@Reza,

Glad this was helpful!

Reply to this Comment

I meant any kind of analogy, language is not a matter. I need some relevance with already existing thing to understand it better.

Reply to this Comment

when you say scope is always passed as a positional argument, what is the main difference between $scope vs scope

does link scope refer to parent controller $scope if isolated scope is not defined.

I am using a directive to perform two way binding on user input it does not work,. is there something wrong in here

mymodule.controller("MyController", ["$scope", function ($scope){
// code here //
$scope.customer =
{
name: "Rahul",
occupation: "Web Developer",
city: "Bengaluru"
}
}]);
mymodule.directive("update", function(){

return {
restrict: 'E',
link:function(scope, elm, attr) {

scope.textValue = "AngularJS"; // this value is not updating
},
template: "<h3>Here we are using two way binding</h3>"
};
});

///////////////////HTML/////////////////////////
<div>
<p>Using custom directive value of input field should update on div when user enters</p>
<input type="text" ng-model="textValue" />
<update></update>
</div>

Appreciate your request

Reply to this Comment

when you say scope is always passed as a positional argument, what is the main difference between $scope vs scope

does link scope refer to parent controller $scope if isolated scope is not defined.

I am using a directive to perform two way binding on user input it does not work,. is there something wrong in here

mymodule.controller("MyController", ["$scope", function ($scope){
// code here //
$scope.customer =
{
name: "Rahul",
occupation: "Web Developer",
city: "Bengaluru"
}
}]);
mymodule.directive("update", function(){

return {
restrict: 'E',
link:function(scope, elm, attr) {

scope.textValue = "AngularJS"; // this value is not updating
},
template: "<h3>Here we are using two way binding</h3>"
};
});

///////////////////HTML/////////////////////////
<div>
<p>Using custom directive value of input field should update on div when user enters</p>
<input type="text" ng-model="textValue" />
<update></update>
</div>

Appreciate your request

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.