Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
163 views
in Technique[技术] by (71.8m points)

javascript - AngularJS: When to pass $scope variable to function

I am using the TodoMVC app to get better with the AngularJS framework. In the index.html on lines 14-16 you see this:

<form id="todo-form" ng-submit="addTodo()">
    <input id="new-todo" placeholder="What needs to be done?" ng-model="newTodo" autofocus>
</form>

Notice how the ng-submit directive calls the addTodo() function without the newTodo model being passed as an argument.

A short time later I came across the following code in the very same file on line 19:

<input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">

You can see the author decided to pass the allChecked model to the markAll() function this time. If I understand correctly, they could have referenced $scope.allChecked inside the controller instead of passing it in.

Why use two different approaches in the same file? Is one approach better in some circumstances? Is this a case of inconsistency or is there a deeper logic being used?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would prefer to always pass in arguments to the function:

  • It's clearer what parameters the function expects.
  • It's easier to unit-test because all parameters are injected into the function.(good for unit- testing)

Consider the following situation:

$scope.addToDo = function(){
   //This declaration is not clear what parameters the function expects.
   if ($scope.parameter1){
      //do something with parameter2
   }    
}

And even worse:

$scope.addToDo = function(){
    //This declaration is not clear what parameters the function expects.
    if ($scope.someobject.parameter1){ //worse

    }    
}

Because of scope inheritance parameter2 may come from parent scope, accessing parameter2 inside the function creates a tight coupling, also causes troubles when you try to unit-test that function.

If I define the function like this:

//It's clearer that the function expects parameter1, parameter2
$scope.addToDo = function(parameter1, parameter2){
   if (parameter1){
      //do something with parameter2
   }    
}

In case your parameter2 is inherited from parent scope, you could still pass it in from the view. When you do unit-testing, it's easy to pass all parameters.

If you have ever worked with ASP.NET MVC, you would notice something similar: the framework tries to inject parameters into action function instead of accessing it directly from Request or HttpContext object

It's also good in case others have mentioned like working with ng-repeat

In my opinion, Controller and Model in angular are not quite clearly separated. The $scope object looks like our Model with properties and methods (Model contains also logic). People from OOP background would think that: we only pass in parameters that don't belong to object. Like a class Person already has hands, we don't need to pass in hands for every object method. An example code like this:

//assume that parameter1 belongs to $scope, parameter2 is inherited from parent scope.
    $scope.addToDo = function(parameter2){ 
        if ($scope.parameter1){ //parameter1 could be accessed directly as it belongs to object, parameter2 should be passed in as parameter.
            //do something with parameter2
        }   
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...