Skip to main content
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Shawn Slaughter and Scott Stroz
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Shawn Slaughter Scott Stroz ( @boyzoid )

When To Use $scope vs. scope In AngularJS

By 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.

Want to use code from this post? Check out the license.

Reader Comments

10 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

15,640 Comments

@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.

10 Comments

@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!

15,640 Comments

@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.

1 Comments

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.

15,640 Comments

@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.

2 Comments

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.

15,640 Comments

@Jaasir,

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

@Reza,

Glad this was helpful!

2 Comments

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

2 Comments

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

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel