2015-07-10 24 views
5

Próbuję zbudować wózek na zakupy do celów edukacyjnych. Mam następujące kodyKorzystanie z samodzielnego wywoływania funkcji anonimowych

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"); 

Ale ten kod rzuca następujący błąd

Uncaught TypeError: Cannot set property 'createCart' of undefined

Po spędzeniu kilku godzin w internecie i po kilku tutorialach zrobiłem po zmianach w kodzie, a następnie zaczął działać.

Ale ja wciąż nie rozumiem co mam zrobić tutaj

var cart = (function (cart) { 

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


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

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

Czy ktoś proszę mi wyjaśnić, dlaczego kod zaczął działać po przejściu cart || {} ekspresji do funkcji anonimowej? Niektóre szczegółowe wyjaśnienia byłyby świetne. :)

+1

koszyk jest niezdefiniowane w cart.createCart. Powinieneś użyć tej funkcji poza wózkiem. –

+1

funkcja oczekuje "koszyka" jako parametru, bez podania 'cart || {} "nic nie przekazujesz, więc' koszyk' będzie niezdefiniowany. pamiętaj, że IIFE mają całkowicie izolowany zakres –

Odpowiedz

3

Więc bez zmiennej przekazanej do zakresu.

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"); 

Jeśli jednak przekazać zmienną do kontekstu:

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"); 

Więc Iife wygląda następująco:

(function() { })(); 

więc ignorując function masz ()(); w tej drugiej pary nawiasów przekazujesz parametry do function w pierwszym zestawie. Dzieje się tak, ponieważ IIFE tworzy całkowicie nowy, czysty zakres. Dlatego używamy IIFE, ponieważ może on izolować zmienne globalne, których używamy w nich.

więc jeśli masz to:

<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> 

Więc Iife są idealne do kontrolowania tego, co masz w zakresach.

cart || {} JavaScript jest zerowa COALESCE, więc to mówi, przechodzą w koszyku, ale jeśli jest ona zerowa dać pusty obiekt

2

Ponieważ jesteś w postępie deklarowania zmiennej koszyk nie jest jeszcze instancję. Kiedy zamiast tego przejdziemy do pustego obiektu (który to, co oceni cart || {}, wówczas doda metodę do tego obiektu, zwróci go, a wózek będzie tym obiektem, a co robi druga funkcja, jest zasadniczo taki sam jak następujący kod:

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


    return cart; 
}()); 

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

nie mam uruchomić ten kod, ale po przeczytaniu przez niego:

W pierwszym przykładzie, na linii trzech, gdzie dzwonisz cart.createCart, obiekt koszyk nie jeszcze istnieje, funkcja nie zwróciła jeszcze obiektu, który sam określa wewnętrznie!

W drugim przykładzie koszyk obiekt jeszcze nie istnieje, ale dostarczyły Wycofanie migracji do nowego pustego obiektu:

cart || {} 

Tak, wewnątrz funkcji, koszyk jest nowy pusty obiekt, do którego można zastosować właściwość createCart .

EDYCJA: Zamieszczona przeze mnie alternatywna funkcja Erika Lundgrena jest tym, czego potrzebujesz. Jego znaczenie jest wyraźniejsze, ponieważ obiekt koszyka jest wyraźnie utworzony wewnątrz funkcji. Użyć tego! :)

Jedyna rzecz, którą chciałbym dodać, to to, że tak naprawdę nie masz żadnego powodu, aby zrobić to wszystko wewnątrz natychmiast wywoływanego wyrażenia funkcji, w tym konkretnym przypadku. Nie ma niczego, co wymagałoby scopingu. Tak to zrobi:

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

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

Z tym kodem:

(cart || {}) 

są przechodzącą zakres funkcji, a jeśli jest on pusty, przekazać pusty obiekt ({}). Wygląda na to, że masz obiekt cart, a kiedy robisz var cart = (function ...., nadpisujesz go.

Może Twój obiekt musi być nazywany Cart z wielkich i działa zbyt:

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