2015-07-10 108 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()... 
    });