2008-10-15 11 views
16

Jak widać w dzienniku zmian Mozilli dla JavaScript 1.7, dodano zadanie destrukturyzacji. Niestety nie jestem bardzo lubiący składni (dlaczego napisać i B dwukrotnie):Przyporządkowanie zadań w JavaScript

var a, b; 
[a, b] = f(); 

Coś takiego byłoby dużo lepiej:

var [a, b] = f(); 

To nadal będzie kompatybilny wstecz . Zwalczanie destrukcji w stylu Pythona nie będzie kompatybilne wstecz.

Zresztą najlepszym rozwiązaniem dla JavaScript 1.5, które udało mi się wymyślić to:

function assign(array, map) { 
    var o = Object(); 
    var i = 0; 
    $.each(map, function(e, _) { 
     o[e] = array[i++]; 
    }); 
    return o; 
} 

Który działa jak:

var array = [1,2]; 
var _ = assign[array, { var1: null, var2: null }); 
_.var1; // prints 1 
_.var2; // prints 2 

Ale to naprawdę jest do bani bo _ nie ma sensu. To tylko pusta skorupa do przechowywania nazw. Ale niestety jest to konieczne, ponieważ JavaScript nie ma wskaźników. Na plus można przypisać wartości domyślne w przypadku, gdy wartości nie są dopasowane. Zauważ też, że to rozwiązanie nie próbuje ciąć tablicy. Więc nie możesz zrobić czegoś takiego jak {first: 0, rest: 0}. Ale można to łatwo zrobić, gdyby ktoś chciał tego zachowania.

Jakie jest lepsze rozwiązanie?

Odpowiedz

23

pierwsze, var [a, b] = f() działa dobrze w JavaScript 1.7 - spróbuj!

Po drugie, można wygładzić składnię użytkowaniu nieznacznie użyciu with():

var array = [1,2]; 
with (assign(array, { var1: null, var2: null })) 
{ 
    var1; // == 1 
    var2; // == 2 
} 

Oczywiście, to nie będzie można modyfikować wartości istniejących zmiennych, więc IMHO jest to dużo mniej użyteczne niż funkcja JavaScript 1.7. W kodzie piszę teraz, właśnie zwracam obiekty bezpośrednio i odwołuję się do ich członków - poczekam, aż funkcje 1.7 staną się szerzej dostępne.

+0

Dzięki! To naprawia jeden z minusów :) –

+2

Na dzień dzisiejszy 'var [a, b] = [1,2];' powoduje błąd składni w Chrome. – Marcin

+9

@Marcin: JavaScript 1.7 to [język dostępny tylko w przeglądarce Mozilla] (http://stackoverflow.com/questions/1330498/what-is-cross-browser-support-for-javascript-1-7s-new-features-specifically -ar). – Shog9

4

Nie potrzebujesz sztucznej zmiennej "_". Można bezpośrednio stworzyć „globalną” zmiennych za pomocą zakresu okno obiektu:

window["foo"] = "bar"; 
alert(foo); // Gives "bar" 

Oto kilka kolejnych punktach:

  • I nie byłoby nazwać tę funkcję „przypisać” bo to jest zbyt ogólne warunek.
  • Aby bardziej przypominać składnię JS 1.7, chciałbym, aby funkcja przyjęła miejsce docelowe jako pierwszy argument , a źródło jako drugi argument .
  • Posługiwanie się literałem obiektu do przekazywania zmiennych docelowych jest fajne, ale można go pomylić z destrukturyzacją JS 1.7, gdzie miejsce docelowe jest w rzeczywistości obiektem, a nie tablicą. Wolę po prostu używać rozdzielanej przecinkami listy nazw zmiennych jako łańcucha znaków.

Oto co wymyśliłem:

function destructure(dest, src) { 
    dest = dest.split(","); 

    for (var i = 0; i < src.length; i++) { 
     window[dest[i]] = src[i]; 
    } 
} 

var arr = [42, 66]; 

destructure("var1,var2", arr); 

alert(var1); // Gives 42 
alert(var2); // Gives 66 
+2

Jedyna rzecz, z którą się zgadzam to to, że destruktura może być lepszą nazwą. * źródło, miejsce docelowe jest w stylu unix. * wypełnianie globalnego zasięgu nie jest miłe. Nie prowadzi do kompozycyjności. * Zapisywanie zmiennych wyjściowych jako ciągu jest męczące i trudniejsze do sprawdzenia przez redaktora. Jak pisanie SQL. –

+0

@AndersRuneJensen Ponieważ to naśladuje zadanie, miejsce docelowe powinno prawie na pewno znajdować się po lewej stronie - w ten sposób wygląda ono jak '[var1, var2] = arr'. A 'destructure' jest okropnym, nie ujawniającym intencji nazwą. Myślę, że 'assign' jest lepszy - w końcu to * ma * być ogólną funkcją użyteczności. Jeśli nie, to może "massAssign"? –

0

W standardowym JavaScript przyzwyczajamy się do wszystkich rodzajów brzydoty i emulacji destructuring zadanie przy użyciu zmiennej pośredniej nie jest tak źle:

function divMod1(a, b) { 
    return [ Math.floor(a/b), a % b ]; 
} 

var _ = divMod1(11, 3); 
var div = _[0]; 
var mod = _[1]; 
alert("(1) div=" + div + ", mod=" + mod); 

Jednak myślę, że następujący wzór jest bardziej idomatic:

function divMod2(a, b, callback) { 
    callback(Math.floor(a/b), a % b); 
} 

divMod2(11, 3, function(div, mod) { 
    alert("(2) div=" + div + ", mod=" + mod); 
}); 

Należy zauważyć, że zamiast zwracania dwóch wyników jako tablicy, przekazujemy je jako argumenty do funkcji wywołania zwrotnego.

(Patrz kod uruchomiony na http://jsfiddle.net/vVQE3/)

1

Oto co zrobiłem w PHPstorm 10:

Plik -> Ustawienia -> Języki & Konstrukcje -> ...

... ustaw wersję językową JavaScript na np JavaScript 1.8.5 ...

-> kliknij Zastosuj.