2010-07-22 10 views
5

Eksperymentowałem ze wzorcem projektowym w Javascript, który pozwoliłby mi uzyskać funkcje, które wydają się być singletonami, które mogą być przesłonięte przez funkcje instancji.A (nieco niejasne) pytanie o dziedziczenie JavaScriptu

Oto krótki przykład:

Date.tomorrow = function() { 
    return Date.today().add(1).days(); 
} 

(function(p) { 

    p.tomorrow = function() { 
    var date = this.clone().clearTime(); 
    return date.equals(Date.tomorrow()); 
    } 

})(Date.prototype); 

więc istnieją dwa tomorrow() funkcje. Wywołany z funkcji Data bezpośrednio:

>>> Date.tomorrow() 
=> Fri Jul 23 2010 00:00:00 GMT-0500 (CST) { _orient=1, more...} 

Ale jeśli instancję pierwszej instancji Data:

>>> var date = new Date() 
>>> date.tomorrow() 
=> false 

Wyjeżdżam dużo się jak jestem pewien, że można powiedzieć, ale miejmy nadzieję, zdobyć punkt. Moje pytanie brzmi: jaka jest relacja pierwszej funkcji tomorrow() do obiektu Date? Do czego dokładnie się przywiązuje?

Załóżmy, że robiłeś to z normalną funkcją, która nie miała być konstruktorem. Czy można wywołać rozszerzoną funkcję z pierwotnej funkcji?

W funkcji konstruktora, można to zrobić:

this.constructor.functionName(); 

ale jeśli funkcja nie jest używana jako konstruktor, oczywiście odniesienie constructor nie istniałaby. Czy istnieje inny sposób dostępu do tej rozszerzonej funkcji?

Impuls kryjący się za tym pytaniem wynika z mojej pracy polegającej na reorganizacji kodu JS dla projektu. Wdrażamy system Sprockets, aby podzielić nasz kod źródłowy na moduły, w których w zasadzie dekorowaliśmy podstawowy obszar nazw, zamiast pakować wszystko razem w jedną nieczytelną definicję obiektu wbudowanego.

Mamy dość epicką dużą kombinację zdarzeń, która dobrze jest podzielić na osobne funkcje, ale wolałbym nie wywoływać poszczególnych funkcji osobno; zamiast tego chciałbym superfunkcji, która wywołuje wszystkie podfunkcje za jednym zamachem.

Zawsze można utworzyć funkcję all() lub coś takiego, aby to osiągnąć, ale wyglądałoby znacznie czystiej z punktu widzenia API, jeśli wywołanie funkcji najwyższego poziomu wykonało wszystkie podfunkcje, które zostały do ​​niej dołączone.


Dzięki odpowiedzi Francisco mam teraz działającą realizację tego, o czym myślałem. Oto przykład na wypadek, gdyby ktoś był ciekawy.

var Namespace = {}; 

var Namespace.wireup = (function() { 

    return function() { 
    var self = arguments.callee; 
    self.eventWireup1(); 
    self.eventWireup2(); 
    }; 

})(); 

(function (W) { 

    function eventWireup1() { console.log('first function'); }; 
    function eventWireup2() { console.log('second function'); }; 

    $.extend(W, { 
    eventWireup1: eventWireup1, 
    eventWireup2: eventWireup2 
    }); 

})(Namespace.wireup); 

Zaletą tego rozwiązania jest to, że można to zrobić:

>>> Namespace.wireup.eventWireup1(); 
=> first function 
>>> Namespace.wireup.eventWireup2(); 
=> second function 
>>> Namespace.wireup(); 
=> first function 
=> second function 
+1

Po prostu z ciekawości; czy spojrzałeś na Yahoo! Biblioteka wydarzeń? Wiem, że to nie jest dokładnie to, o co pytasz ... ale wygląda na to, że to, o co prosisz, może nie być potrzebne, jeśli masz przyzwoitą alternatywę? (http://developer.yahoo.com/yui/event/) – Steve

+0

@Steve moje pytanie nie jest tak naprawdę związane z wiązaniem zdarzeń per se, ale raczej formą modularyzacji. Istnieją pewne typy wireupów zdarzeń, które chcę wywołać zarówno pośrednio, jak i jawnie. Plus już używam jQuery do wydarzeń, które lubię lepiej niż YUI osobiście. –

Odpowiedz

0

Od arguments.callee została zaniechana pomyślałem, że powinienem aktualizować to pytanie z przykładem tego, co zakończyłem przejściem do tego, jest zarówno bardziej poprawne, jak i kompatybilne z trybem ścisłym.

var Namespace = {}; 

(function() { 
    Namespace.wireup = function self() { 
    self.eventWireup1(); 
    self.eventWireup2(); 
    } 
})(); 

(function (self) { 
    self.eventWireup1 = function() { console.log('first function') } 
    self.eventWireup2 = function() { console.log('second function') } 
})(Namespace.wireup); 
2

Data jest funkcja() obiektu okna, a ty mocowania innej funkcji do funkcji. Dziwne?

Spróbuj tego:

function a() 
{ 
    return 10; 
} 

a.e = "oO"; 

typeof(a); 
typeof(a.e); 

Aby uzyskać dostęp do e od wewnątrz można użyć właściwości wywoływanego z argumentami, jak:

function a() { 
    return arguments.callee.e; 
} 

a.e = "Oo" 

a(); 
+0

Tak, to dziwne; ale ogólnie dziedziczenie JavaScript jest dziwne;) Moje pytanie brzmi - czy możesz uzyskać dostęp do a.e z samej funkcji()? Jak byś to zrobił bez używania w pełni kwalifikowanej nazwy? –

+0

'arguments.callee' jest tym, czego szukałem! Dzięki. –