角度参考误解

时间:2016-05-01 05:47:28

标签: javascript angularjs

正如我刚刚意识到的那样,我并没有在Angular中获得范围。仔细查看var Cart:我尝试访问cartItems变量,就像cartItems: cartItems一样,但这并不起作用。如果我把它包装成函数,我从闭包中得到这个变量(就像chrome dev工具所说)。有人可以解释我的区别,为什么我不能直接从cartItems对象访问Cart?感谢。

P.S。尝试使用this代替var代替变量,没有任何区别。

.factory('Cart', function(FirebaseUrl, $firebaseArray, $firebaseObject, $state, Auth) {

    var cartsRef = new Firebase(FirebaseUrl + '/carts');
    var userId, cartRef, cartItems;

    Auth.$onAuth(function(authData) { // triggers on entering the page
      userId = authData && authData.uid;
      cartRef = new Firebase(cartsRef + '/' + userId);
      cartItems = $firebaseArray(cartRef);
    });

    var Cart = {
      getCartItems: function() {
        return cartItems;
      },
      cartItems: cartItems // this won't work
    };  

    return Cart;
  });

编辑:为了理解我的问题,我将提供一大块控制器代码:

 .controller('CartCtrl', function(Cart, Auth) {
    var cartCtrl = this;
    cartCtrl.cartItems = Cart.getCartItems(); // returns items
    cartCtrl.cartItems1 = Cart.cartItems; // returns undefined. Why?

1 个答案:

答案 0 :(得分:2)

执行cartItems: cartItems后,您将该属性分配给cartItems当前值 - 这不算什么!

当您执行getCartItems: function () ....时,您无法在稍后的某个时间点访问cartItems - 此功能将被调用。只有在那时,当它被调用时,您是否正在访问已设置的cartItems

您正在查看的内容并非$scope,或JS范围,它的参考资料。你按照价值制造了一个""分配,在这两个不同的时间点不同。

这是一个简单的例子:

var foo = 'foo';

var fooAsValue = foo;

function fooAsFunction () {
  return foo;
}

foo = 'bar';

console.log(fooAsValue) // "foo"
console.log(fooAsFunction()) // "bar"

正如您所看到的,当您将fooAsValue分配给foo时,您将从该时间点获取值'foo'

当您更改foo时,另一个变量fooAsValue已经从之前捕获了它的值 - 这并没有改变。当您执行fooAsFunction后,在将其分配给'bar'后,您会收到该新值,因为您现在已经拥有新值,因此引用该变量。

如果它是对象引用,则会有所不同,并且更像是指针

让我们来看看这个例子:

var anObject = {
  foo: {bar: 'foobar'}
};

var fooAsReference = anObject.foo;

anObject.foo.bar = 'hello world';

console.log(fooAsReference) // {bar: 'hello world'}

这是事情变化的地方。正在对一个对象的属性进行赋值,该属性指向另一个对象。

此处我们指向anObject.foo,我们更改anObject.foo.bar,我们实际上保留了原始引用,因为它没有发生变化 - 更改发生在对象树的下方。我们看到这种变化,因为我们的参考没有改变。更改的是我们引用的对象内部,而不是我们指向的值。

这有点棘手,但是如果你亲自动手这两种不同的场景,即使它只是一个带有几个变量和一些控制台输出的空白文件,它也会开始真的点击。

所以要把它们全部重新组合起来,

cartItems: cartItemscartItems进行分配,但尚未拥有值。所以这将是空的。

getCartItems会返回cartItems,在您调用它时可能会有一个值。这是因为Auth.$onAuth已经解雇,并且已经完成了作业cartItems = $firebaseArray(cartRef);然后您最终在分配后调用函数getCartItems ,然后您就拥有了值。

你能做什么

var Cart = {cartItems: []};

Auth.$onAuth(function () {
  // ...
  // Now we're talkin!
  Cart.cartItems = $firebaseArray(cartRef);
});

return Cart;

我们可以将单一的事实来源移到Cart.cartItems本身,而不是让Cart.cartItems指向我们所知道的事物。更新该属性,而不是单独的变量。

还可以将命名简化为Cart.items,因为我们已经知道"这些项目属于购物车" :)