4

from the 《ng-book》, It says:

Due to the nature of JavaScript itself and how it passes by value vs. reference, it’s considered a best-practice in Angular to bind references in the views by an attribute on an object, rather than the raw object itself.

.....

In this case, rather than updating the $scope.clock every second, we can update the clock.now property. With this optimization, we can....

I don't know why because 《JavaScript: The Definitive Guide》 says:

Is there really any fundamental difference between the variable i and the property i of an object o? The answer is no. Variables in JavaScript are fundamentally the same as object properties.

In this book:

$scope.time = { now: new Date()} 

is better than

$socpe.time = new Date();
Ryan Yiada
  • 4,739
  • 4
  • 18
  • 20
  • see http://jsfiddle.net/arunpjohny/4GcQ5/1/ and http://jsfiddle.net/arunpjohny/4GcQ5/2/ – Arun P Johny Feb 20 '14 at 09:15
  • See http://www.youtube.com/watch?v=ZhfUv0spHCY#t=1760 for clear explanation from AngularJS themselves – elclanrs Feb 20 '14 at 09:17
  • the difference is when you assign a new value to those variables from a sibling or an isolated scope – Arun P Johny Feb 20 '14 at 09:18
  • Bottom line -- "Whenever you have an ng-model there's **got** to be a dot in there somewhere. If you don't have a dot, you're doing it wrong." -- Miško Hevery. – elclanrs Feb 20 '14 at 09:24
  • possible duplicate of [What are the nuances of scope prototypal / prototypical inheritance in AngularJS?](http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs) – Stewie Feb 20 '14 at 10:07

2 Answers2

2

Consider this sample HTML:

<div ng-app>
    <div ng-controller="MyController">
        <div>{{rawObj}}</div>
        <div>{{obj.prop}}</div>
        <div ng-if="isShown">
            <input ng-model="rawObj" />
            <input ng-model="obj.prop" />
            <span>{{readOnly}}</span>
        </div>
    </div>
</div>

And in js you have a controller:

 function MyController($scope){
    $scope.rawObj = "raw value";
    $scope.obj = {
        prop: "property of object"
    }
    $scope.readOnly = "read only";
    $scope.isShown = true;
 }

If you start typing into the input with ng-model="rawObj" the rawObj as property of $scope in MyController won't be modified, but a new property rawObj will be created in the ng-if's scope. If i haven't put the ng-if directive on the wrapping div everything would work ok. The is occuring when you have a directive on an element between the input and the element with ng-controller (in that case) which creates its own non-isolated scope. And many directives do such as: ng-if or ng-repeat.

If you reference a property of an object in ng-model it will "look for" the object in parent scopes and find the proper scope.

Check it out on a fiddle: http://jsfiddle.net/VC5WK/

This is due to how prototypal inheritance in javascript works as the previous answears state.

kamilkp
  • 9,690
  • 6
  • 37
  • 56
0

Because the $scope object will not be the same object when accessed from a different controller.

//In controller A:
$scope.time = 1;

//In controller B:
alert($scope.time) may not be 1.

This is because the $scope object is a new object that inherits from an existing $scope object. If you change anything on the new object, the change won't be reflected on the existing $scope object, unless it is accessed through an intermediate object.

The equivalent can be simulated with regular javascript objects:

var objectA = {time:1, prop:{time:1}};

//setup inheritance
function classB() {}
classB.prototype = objectA;

//objectB inherits the same properties as objectA
var objectB = new classB();

objectB.time = 2;
objectB.prop.time = 2;

alert(objectA.time); //=1 changes to B were not transfered to A
alert(objectA.prop.time); //=2
Kernel James
  • 3,752
  • 25
  • 32