Mam ten fragment kodu (wzięty z tego pytania ):
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err)
return done(err);
var pending = list.length;
if (!pending)
return done(null, results);
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
if (!--pending)
done(null, results);
});
} else {
results.push(file);
if (!--pending)
done(null, results);
}
});
});
});
};
Staram się podążać za tym i myślę, że rozumiem wszystko, z wyjątkiem końca, gdzie jest napisane !--pending
. W tym kontekście, co robi to polecenie?
Edycja: Doceniam wszystkie dalsze komentarze, ale na pytanie udzielono odpowiedzi wiele razy. W każdym razie dzięki!
javascript
decrement
prefix-operator
not-operator
Kieran E.
źródło
źródło
!~--[value] ^ true
Nazywam taki kod „zabezpieczeniem pracy”-->
operatora?Odpowiedzi:
!
odwraca wartość i daje przeciwną wartość logiczną:--[value]
odejmuje jeden (1) od liczby, a następnie zwraca tę liczbę do pracy z:Tak,
!--pending
odejmuje jeden z toku, a następnie powraca przeciwieństwo jego truthy / wartość falsy (czy nie jest0
).I tak, postępuj zgodnie z ProTip. Może to być powszechny idiom w innych językach programowania, ale w przypadku większości deklaratywnych programów JavaScript wygląda to zupełnie obco.
źródło
--
działa tylko na zmienne; nie można zastosować go ogólnie do wartości.validSimpleAssignmentTarget
s. Obejmuje to odniesienia do identyfikatora i odwołania do właściwości.--0
i--1
nie będzie działać. Literały liczbowe nie są prawidłowym wyrażeniem po lewej stroniei > -1
rzeczy niżi--
(i tak przy okazji, zapomniałeśi = init() - 1
). Do tego służą idiomy… i każdy programista powinien się ich nauczyć.To nie jest operator specjalny, to 2 standardowe operatory jeden po drugim:
--
)!
)Powoduje
pending
to zmniejszenie wartości, a następnie sprawdzenie, czy jest równa zero.źródło
if(pending === 1)
?if( pending === 1 ) { done... } else { pending = pending - 1; }
.Szereg odpowiedzi opisuje, co robi to polecenie, ale nie wyjaśnia , dlaczego tak się tutaj dzieje.
Pochodzę ze świata C i czytam
!--pending
jako „odliczajpending
i sprawdzam, czy wynosi zero”, nie myśląc o tym. Jest to idiom, który moim zdaniem powinien znać programiści w podobnych językach.Ta funkcja służy
readdir
do uzyskania listy plików i podkatalogów, które zbiorczo nazywam „wpisami”.Zmienna
pending
śledzi, ile z nich pozostało do przetworzenia. Zaczyna się od długości listy i odlicza w dół do zera podczas przetwarzania każdego wpisu.Wpisy te mogą być przetwarzane poza kolejnością, dlatego konieczne jest odliczanie, a nie zwykła pętla. Po przetworzeniu wszystkich wpisów oddzwanianie
done
jest wywoływane w celu powiadomienia pierwotnego dzwoniącego o tym fakcie.W pierwszym wywołaniu
done
jest poprzedzone znakiemreturn
, nie dlatego, że chcemy zwrócić wartość, ale po prostu, aby funkcja przestała działać w tym momencie. Byłoby czystszym kodem upuścićreturn
i umieścić alternatywę welse
.źródło
!--pending
zawodzi wiele linters i wytycznych dotyczących stylu. Wystarczy mi powiedzieć, że prawdopodobnie nie jest to idiomatyczne (niezależnie od tego, czy alternatywa jest „lepsza”).int
siębool
domyślnie i nie ma absolutnie nic wspólnego z używaniem!--
.To jest skrót.
!
nie jest".--
zmniejsza wartość.!--
Sprawdza więc , czy wartość uzyskana z zanegowania wyniku zmniejszenia wartości jest fałszywa.Spróbuj tego:
Pierwszy jest fałszywy, ponieważ wartość x wynosi 1, drugi jest prawdziwy, ponieważ wartość x wynosi 0.
Uwaga dodatkowa:
!x--
najpierw sprawdza, czy x jest fałszem, a następnie go zmniejsza.źródło
!
, podczas gdy pre-fix ma niższy priorytet. JavaScriptvar x = 2; console.log(!x--); console.log(!x--); console.log(!x--);
). Chociaż poprawka--
po wykonaniu może zostać wykonana jako pierwsza, jej wartością zwracaną jest wartość zmiennej przed zmniejszeniem ( Decrement Opperator ).!--
zwraca negację wyniku zmniejszenia wartości”. Tylko kod zewnętrzny, taki jakconsole.log()
, sprawdza, czy jego zawartość jest zgodna z prawdą.!
jest operatorem JavaScript NOT--
jest operatorem przedsprzedaży. Więc,źródło
--
operator mógłby pracować ze stałą ... może miałeś na myśli--x
zamiast--0
?znaczy
znaczy
źródło
if(0 == pending)
ze względu na potencjał literówek.if(0 = pending)
jest błędem składni.if(pending = 0)
to zadanie, które spowoduje mylące zachowanie gotowego kodu.if(0 = pending)
nie jest to błąd składniowy - analizuje się dobrze - ale błąd referencyjny, ponieważ0
nie można go przypisać (zob. ECMA-262 (wydanie 6), sekcja 12.14.1).To nie operator, a za nim miejscowy środek do dekrementacji.
Więc jeśli
pending
był liczbą całkowitą o wartości 1:źródło
Po prostu maleje
pending
o jeden i uzyskuje logiczne uzupełnienie (negację). Logicznym uzupełnieniem dowolnej liczby różnej od 0 jestfalse
, dla 0 jesttrue
.źródło
Wyjaśnienie
To jest 2 operatorów, a
!
i a--
Zatem
--
zmniejszenie x o 1, a następnie!
zwraca true, jeśli x jest teraz 0 (lub NaN ...), false, jeśli nie jest. Możesz przeczytać ten idiom coś w stylu „zmniejszamy x, a jeśli to czyni zero…”Jeśli chcesz, aby był bardziej czytelny, możesz:
Wypróbuj to:
Fiddle (kod wypróbowania)
źródło
Prawdziwym problemem jest tutaj brak odstępu między dwoma operatorami
!
i--
.Nie wiem, dlaczego ludzie mają w głowie, że nigdy nie można użyć spacji za
!
operatorem. Myślę, że wynika to ze sztywnego stosowania mechanicznych reguł białych znaków zamiast zdrowego rozsądku. Prawie każdy standard kodowania, który widziałem, zabrania spacji po wszystkich jednostkowych operatorach, ale dlaczego?Jeśli zdarzały się przypadki, w których wyraźnie potrzebujesz tej przestrzeni, jest to jedna sprawa .
Rozważ ten fragment kodu:
Nie tylko są
!
i--
zmiksowane razem, masz to(
je również przeciwko niemu. Nic dziwnego, że trudno powiedzieć, co jest z tym związane.Trochę więcej białych znaków sprawia, że kod jest znacznie wyraźniejszy:
Jasne, jeśli jesteś przyzwyczajony do reguł mechanicznych, takich jak „brak spacji w parenach” i „brak spacji po jednostkowym operatorze”, może to wydawać się nieco obce.
Ale spójrz, jak dodatkowe białe znaki grupują i oddzielają różne części
if
wyrażenia i wyrażenia: Masz--pending
, więc--
jest to oczywiście jego własny operator i ściśle z nim związanypending
. (Zmniejszapending
i zwraca obniżony wynik.) Następnie zostałeś!
oddzielony od tego, więc jest to oczywiście wyraźny operator, negujący wynik. Wreszcie, maszif(
i)
otaczasz całym wyrażeniem, aby uczynić toif
stwierdzeniem.I tak, usunąłem spację między
if
i(
, ponieważ(
należy doif
. Nie(
jest to część jakiejś(!--
składni, ponieważ wydaje się, że jest w oryginale,(
jeśli jest częścią składniif
samej instrukcji.Biała spacja służy tutaj do przekazywania znaczenia , zamiast przestrzegać jakiegoś standardu kodowania mechanicznego.
źródło
!--
to jakiś operator javascript, którego nie znałem. Dlaczego nie użyć nawiasów, aby uczynić je jeszcze bardziej wyraźnym?if(!(--pending))
++
lub--
, ale wielu nie zakazują korzystania niż istotne pomieszczenia, takie jak po!
operatora przedrostka i mniej istotnych nawiasach.