正如我刚刚意识到的那样,我不太了解Angular的作用域。仔细观察var Cart:我尝试访问cartItems变量,就像cartItems: cartItems一样,但这不起作用。如果将其包装为函数,则会从闭包中获取此变量(如chrome dev工具所说)。有人可以解释一下两者之间的区别,为什么我不能直接从cartItems对象访问Cart?谢谢。

附言尝试对变量使用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?

最佳答案

当您执行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,因为我们已经知道“这些商品属于购物车” :)

08-26 08:23