2015-07-10 76 views
5

我正在尝试构建用于学习目的的购物车。我有以下代码使用自我调用匿名函数

HTML

<div id="MyCart" class="product-cart"> 
    <ul> 
     <li class="item"></li> 
     <li class="item"></li> 
     <li class="item"></li> 
    </ul> 
</div> 

JS

var cart = (function() { 

    cart.createCart = function (cartId) { 
     console.log(cartId); 
     cartId = document.getElementById(cartId); 
    } 


    return cart; 
}()); 

var shoopingCart = cart.createCart("MyCart"); 

但这个代码抛出以下错误

Uncaught TypeError: Cannot set property 'createCart' of undefined

在网上花费几个小时后遵循一些教程,我做了下面的代码更改,然后开始工作。

但我依然不明白我在这里做

var cart = (function (cart) { 

    cart.createCart = function (cartId) { 
     console.log(cartId); 
     cartId = document.getElementById(cartId); 
    } 


    return cart; 
}(cart || {})); 

var shoopingCart = cart.createCart("MyCart"); 

能有人请解释我为什么代码开始传递cart || {}表达到匿名函数后,开始工作?一些详细的解释会很好。 :)

+1

车在cart.createCart不确定的。您应该使用外部购物车功能。 –

+1

函数期待'cart'作为参数,而不会传递'cart || {}'你没有任何东西,所以'cart'将会是未定义的。请记住,IIFE有一个完全隔离的范围 –

回答

3

所以没有变量传入范围。

var cart = (function (cart) { 

    // can't add a property or method onto undefined. 
    cart.createCart = function (cartId) { 
     console.log(cartId); 
     cartId = document.getElementById(cartId); 
    } 


    return cart; 
}()); // without any value here^cart will be undefined. 

var shoopingCart = cart.createCart("MyCart"); 

但是,如果变量传递给上下文:

var cart = (function (cart) { 

    // cart now is an object which you can attach a property or method 
    cart.createCart = function (cartId) { 
     console.log(cartId); 
     cartId = document.getElementById(cartId); 
    } 


    return cart; 
}(cart || {})); // pass in cart, or if it is null a new object {} 

var shoopingCart = cart.createCart("MyCart"); 

因此,一个IIFE看起来是这样的:

(function() { })(); 

所以忽略了function你在第二对获得()();的括号中,您将参数传递给第一组中的function。这是因为IIFE创造了一个全新的清洁范围。这就是我们使用IIFE的原因,因为它可以隔离我们在其中使用的全局变量。

,所以如果你有这样的:

<script> 

var someGlobalVariable = "hey"; 

(function() { 

    // using someGlobalVariable here will be fine 

    var myIIFEScopedVariable = "ho"; 

})(); 

// trying to access myIIFEScopedVariable here will fail because again, it hasn't been defined here. 

</script> 

所以IIFE的是伟大的控制你在作用域。

cart || {}是一个JavaScript空聚结,所以说,在通过车,但如果它是空给它一个空的对象

2

因为你在声明cart变量则还不实例化的进展。当你传递一个空的对象时(这是cart || {}将评估它的方法,然后将该方法添加到该对象,返回它并且购物车将是该对象。第二个函数的作用基本上与以下代码相同:

var cart = (function() { 
    var cart = {}; 
    cart.createCart = function (cartId) { 
     console.log(cartId); 
     cartId = document.getElementById(cartId); 
    } 


    return cart; 
}()); 

var shoopingCart = cart.createCart("MyCart"); 
2

我没有,但通过它阅读运行这段代码:三线,在那里你叫cart.createCart

在你的第一个例子中,对象不仍然存在,函数尚未返回它本身在内部引用的对象!

在第二个例子中,对象仍然不存在,但您提供一个退回到一个新的空白对象:

cart || {} 

所以,在函数内部,是一个新的空白对象,应用createCart属性。

编辑:Erik Lundgren刚发布的替代功能就是你需要的。它的意思更清晰,因为购物车对象在函数内部清楚地实例化。使用它! :)

我会补充的唯一的事情是,你真的没有任何理由在立即调用的函数表达式中完成所有这些,在这种情况下。没有什么需要范围界定的。因此,这将做到:

var cart = {}; 
cart.createCart = function (cartId) { 
    console.log(cartId); 
    cartId = document.getElementById(cartId); 
} 

var shoopingCart = cart.createCart("MyCart"); 
1

有了这个代码:

(cart || {}) 

你传递函数的范围,如果它是空的,你传递一个空对象({})。看起来好像你有一个cart对象,而当你制作var cart = (function ....时,你将覆盖它。

也许你的对象必须被称为Cart与大写字母,它也能工作:

var cart = (function() { 
     Cart.createCart()... 
    });