2010-04-19 15 views
13

Na przykład ten kod:Czy istnieje sposób na złapanie próby uzyskania dostępu do nieistniejącej właściwości lub metody?

function stuff() { 
    this.onlyMethod = function() { 
    return something; 
    } 
} 

// some error is thrown 
stuff().nonExistant(); 

Czy istnieje sposób, aby zrobić coś podobnego PHP __call jako awaryjnej z wnętrza obiektu?

function stuff() { 
    this.onlyMethod = function() { 
    return something; 
    } 
    // "catcher" function 
    this.__call__ = function (name, params) { 
    alert(name + " can't be called."); 
    } 
} 

// would then raise the alert "nonExistant can't be called". 
stuff().nonExistant(); 

Może wytłumaczę trochę więcej, co robię.

Obiekt zawiera inny obiekt, który ma metody, które powinny być dostępne bezpośrednio przez ten obiekt. Ale te metody są różne dla każdego obiektu, więc nie mogę po prostu ich skierować, muszę mieć możliwość wywoływania ich dynamicznie.

Wiem, że mógłbym uczynić obiekt w środku własnością głównego obiektu stuff.obj.existant(), ale zastanawiam się, czy mógłbym tego uniknąć, ponieważ główny obiekt jest pewnego rodzaju otoką, która chwilowo dodaje trochę funkcjonalności (i ułatwia dostęp do obiektu w tym samym czasie).

+2

Nie możesz użyć próby złapania? Lub czegoś mi brakuje? – Bipul

+0

musi się zdarzyć wewnątrz funkcji. –

+0

Dodam, że w najnowszych wersjach JS/ES są w rzeczywistości meta-metody gettera i settera. –

Odpowiedz

9

Istnieje sposób zdefiniowania ogólnego programu obsługi wywołań na nieistniejących metodach, ale jest on niestandardowy. Zamówienie na noSuchMethod dla przeglądarki Firefox. Umożliwia dynamiczne przekierowywanie wywołań do niezdefiniowanych metod. Wydaje się, że v8 jest również dla niego getting support.

Aby go użyć, należy zdefiniować tę metodę na dowolnym obiekcie:

var a = {}; 

a.__noSuchMethod__ = function(name, args) { 
    console.log("method %s does not exist", name); 
}; 

a.doSomething(); // logs "method doSomething does not exist" 

Jednak jeśli chcesz metody cross-przeglądarki, a następnie proste bloki try-catch jeśli droga:

try { 
    a.doSomething(); 
} 
catch(e) { 
    // do something 
} 

Jeśli nie chcesz pisać try-catch w całym kodzie, możesz dodać wrapper do głównego obiektu, przez który będą kierowane wszystkie wywołania funkcji.

function main() { 
    this.call = function(name, args) { 
     if(this[name] && typeof this[name] == 'function') { 
      this[name].call(args); 
     } 
     else { 
      // handle non-existant method 
     } 
    }, 
    this.a = function() { 
     alert("a"); 
    } 
} 

var object = new main(); 
object.call('a') // alerts "a" 
object.call('garbage') // goes into error-handling code 
+0

wielkie dzięki! teraz mam z czym pracować. :) –

+0

trycatch nie działa, ponieważ odcina przepływ kodu użytkownika ("Jak wznowić operację?"), A po drugie, nie ma sposobu na uzyskanie dostępu do obiektu z obsługi catch. – Pacerier

2

Można również sprawdzić, czy metoda istnieje.

if(a['your_method_that_doesnt_exist']===undefined){ 
//method doesn't exist 
} 
1

Wygląda na to, że znasz swoją drogę do JS. Niestety, nie znam takiej funkcji w języku i jestem pewien, że ona nie istnieje. Najlepszym rozwiązaniem, moim zdaniem, jest użycie jednolitego interfejsu i rozszerzenie go lub rozszerzenie prototypów, z których dziedziczą obiekty (następnie można użyć instanceof przed przejściem do wywołania metody) lub użyć nieco uciążliwego operatora '& &' w celu uniknięcia dostępu nieistniejących właściwości/metod:

obj.methodName && obj.methodName(art1,arg2,...); 

Możesz również rozszerzyć prototyp obiektu z sugestią Anuraga za („Połącz”).

9

Cóż, wydaje się, że w harmonii (ES6), będzie sposób, i jest to bardziej skomplikowane w porównaniu do sposobu, w jaki robią to inne programing languages. Zasadniczo, to wiąże się z wykorzystaniem proxy wbudowanego obiektu, aby utworzyć opakowanie na obiekcie i zmodyfikować domyślne zachowanie sposób jej wdrożone na nim:

obj = new Proxy({}, 
     { get : function(target, prop) 
      { 
       if(target[prop] === undefined) 
        return function() { 
         console.log('an otherwise undefined function!!'); 
        }; 
       else 
        return target[prop]; 
      } 
     }); 
obj.f()  ///'an otherwise undefined function!!' 
obj.l = function() {console.log(45);}; 
obj.l();  ///45 

Pełnomocnik prześle wszystkie metody nie obsługiwane przez wozy na normalny obiekt. Więc będzie tak, jakby go tam nie było, a od proxy możesz modyfikować cel.Jest też więcej programów do obsługi, nawet niektóre, które modyfikują otrzymywanie prototypów i setery dla dowolnego dostępu do właściwości tak !.

Jak można sobie wyobrazić, to nie jest dostępna we wszystkich przeglądarkach teraz, ale w Firefoksie można grać z interfejsem Proxy dość proste, wystarczy udać się do MDN docs

To by mnie szczęśliwszy, gdyby udało aby dodać trochę cukru syntaktycznego na tym, ale w każdym razie fajnie jest mieć taką moc w już potężnym języku. Miłego dnia! :)

PD: Nie skopiowałem wpisu w j. Rosettacode, zaktualizowałem go.

+0

Ale to jest bezużyteczne, ponieważ nie działa na obiekcie docelowym, ale na zupełnie nowym obiekcie. Innymi słowy, nie można tego użyć do przechwycenia dostępu do właściwości 'Array'. – Pacerier

Powiązane problemy