Angular $watch 细微差别和工厂没有反映状态变化?

Angular $watch nuance and factory not reflecting state change?

我很难理解为什么工厂不会反映对其基元的更改(作为单例)但它会反映对象..有时..在以下六个场景中。

我有这个工厂:

angular.module('my.module).factory('myfactory', FactoryFunction);
function FactoryFunction(){

  var primitiveVariable = false;
  function togglePrimitive(){
    primitiveVariable = !primitiveVariable
  }
  var dummyObject = {
    isTrue = false;
  }
  function toggleObject(){
    dummyObject.isTrue = !dummyObject.isTrue;
  }
  var myFactory = {
    toggleObject: toggleObject,
    dummyObject: dummyObject,
    togglePrimitive: togglePrimitive,
    primitiveVariable: primitiveVariable
   }
   return myFactory
}

我也有这个指令

angular.module('my.module).directive('myDirective', DirectiveFunction);
DirectiveFunction.$inject['myFactory'];
function DirectiveFunction(){
  return {
    restrict: 'A',
    scope:{},
    link: function(scope, element, attributes, nullcontroller, nulltranslcude){

      //watch1 WONT RUN 
      //watched is undefined even if myFactory.togglePrimitive() runs
      scope.$watch(myFactory.primitiveVariable, function(){
        //do stuff
      });

      //watch2 WONT RUN
      //watched is undefined even if myFactory.togglePrimitive() runs
      scope.$watch(function(){return myFactory.primitiveVariable}, function(){
        //do stuff
      });

      //watch3 WONT RUN
      //not returning something by calling togglePrimitive()?
      scope.$watch(myFactory.togglePrimitive(), function(){
        //do stuff
      });

      //watch4 WILL RUN
      //but now I am not even running the function...?
      scope.$watch(myFactory.togglePrimitive, function(){
        //do stuff
      });

      //watch5 WONT RUN
      scope.$watch(myFactory.dummyObject.isTrue, function(){
        //do stuff
      });

      //watch6 WILL RUN 
      //... seriously??
      //is myObj.val and function(){return myObj.val} NOT the same?
      scope.$watch(function(){return myFactory.dummyObject.isTrue}, function(){
        //do stuff
      });
    }
  }
}

我的问题是,为什么 watch1、watch2、watch3、watch5 不工作而 watch4、wantch6 工作?

我对发生这种情况的原因很感兴趣。这是设计选择吗?目的是什么?

我还想补充一点,function(){ return myFactory.primitiveValue } 不能用作监视表达式,但 function(){ return myFactory.dummyObject.isTrue } 用作监视表达式。有谁知道为什么原始属性与对象的原始属性之间会出现这种偏差?他们都是原始人。当 console.log 来自更新原语的工厂函数时,它会反映更改。当 console.log 来自 return 原始表达式(在 $watch 中)时,它不反映更改。

jsFiddle: https://jsfiddle.net/b0svnjqf/21/

任何人都可以照进来的任何光线,我将不胜感激。

这是因为 watch 表达式采用表示 属性 的字符串或可以在该范围内计算的表达式或函数 getter,return 是一个使用的值用于每个摘要周期的脏检查。

例如:

  scope.$watch(myFactory.primitiveVariable, function(){
    //do stuff
  });

watch 表达式是 myFactory.primitiveVariable 的值而不是 属性 本身,其中:

  scope.$watch(function(){return myFactory.primitiveVariable}, function(){
    //do stuff
  });

运行s 表达式 getter 在每个摘要循环期间作为函数传入以进行脏检查,这将 return 当时 属性 的值。

同样当你这样做时:

  scope.$watch(myFactory.togglePrimitive, function(){
    //do stuff
  });

您正在将函数 togglePrimitive 的引用作为监视表达式传递,它可以是 getter 但您实际上并没有 return 从那里获取任何内容,因此您的监视侦听器将不是 运行 1 次迭代后。

Documentation:

watchExpression: function() | string

Expression that is evaluated on each $digest cycle. A change in the return value triggers a call to the listener.

string: Evaluated as expression

function(scope): called with current scope as a parameter.

除此之外,没有必要更改变量 primitiveVariable 并期望更改会神奇地反映在 myFactory.primitiveVariable 中,它们都是不同的,因为它们是原始的,所以它们不会坚持下去参考文献也是如此。

function FactoryFunction(){
    
  var myFactory ,
      dummyObject = {
         isTrue = false;
      };

  function togglePrimitive(){
    //Set the value directly on the factory instance
    myFactory.primitiveVariable = !myFactory.primitiveVariable
    //or even this.primitiveVariable  = !this.primitiveVariable;
    //But better not to assume "this" as much as you can
  }
  
  function toggleObject(){
     //This is fine as you are modifying property on the reference and the same reference has been set to the dummyObject property of myFactory
     dummyObject.isTrue = !dummyObject.isTrue;
     //or this.dummyObject.isTrue = !this.dummyObject.isTrue;
  }

  myFactory = {
     toggleObject: toggleObject,
     dummyObject: dummyObject, //this should be fine unless you overwrite the variable dummyObject itself
     togglePrimitive: togglePrimitive,
     primitiveVariable: false //Set the value directly
   }  
  
   return myFactory;
}