Что значит "!--" в JavaScript?
у меня есть этот кусок кода (взятый из этого вопроса):
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);
}
});
});
});
};
Я пытаюсь следовать за ним, и я думаю, что понимаю все, кроме ближе к концу, где он говорит !--pending. В этом контексте, что делает эта команда?
Edit: я ценю все дальнейшие комментарии, но на этот вопрос был дан ответ много раз. Все равно спасибо!
10 ответов:
!инвертирует значение и дает вам противоположное логическое значение:!true == false !false == true !1 == false !0 == true
--[value]вычитает один (1) из числа, а затем возвращает это число для работы с:var a = 1, b = 2; --a == 0 --b == 1и
!--pendingвычитает один из ожидающих, а затем возвращает противоположное его значение истинности / ложности (независимо от того, является ли это0).pending = 2; !--pending == false pending = 1; !--pending == true pending = 0; !--pending == falseи да, следуйте простой. Это может быть обычной практикой в других языках программирования, но для большинства декларативный JavaScript с программирование это выглядит довольно чуждо.
Это не специальный оператор, это 2 стандартных оператора один за другим:
- префиксного декремента (
--)- логическое не (
!)Это приводит к
pendingдля уменьшения, а затем проверить, если это ноль.
ряд ответов описывает что эта команда делает, а не почему это делается таким образом здесь.
Я пришел из мира С, и я читаю
!--pendingкак "отсчетpendingи проверить, если он равен нулю", не задумываясь об этом. Это идиома, которую я думаю, что программисты на подобных языках должны знать.функция использует
readdirполучить список файлов и подкаталогов, которые я буду обобщенно называть "записи".переменная
pendingотслеживает, сколько из них остается для обработки. Он начинается с длины списка и отсчитывается вниз к нулю по мере обработки каждой записи.эти записи могут быть обработаны не по порядку, поэтому необходимо вести обратный отсчет, а не просто использовать простой цикл. Когда все записи были обработаны обратный вызов
doneвызывается для уведомления вызывающего этой факт.в первом вызове
doneначинается сreturn, не потому, что мы хотим вернуть значение, а просто заставить функцию прекратить выполнение в этот момент. Это был бы более чистый код, чтобы удалитьreturnи поставить альтернативу вelse.
Это стенографировать.
!"нет".
--уменьшает значение.так
!--проверяет, является ли значение, полученное в результате отрицания результата уменьшения значения, ложным.попробуйте это:
var x = 2; console.log(!--x); console.log(!--x);первый является ложным, так как значение x равно 1, второй является истинным, так как значение x равно 0.
Примечание:
!x--сначала проверит, является ли x ложным, а затем уменьшит его.
!Это JavaScript не оператор
--является оператором предварительного декремента. Итак,x = 1; if (!x) // false if (!--x) // becomes 0 and then uses the NOT operator, // which makes the condition to be true
это не оператор, за которым следует предварительный декремент на месте.
Если
pendingбыло целое число со значением 1:val = 1; --val; // val is 0 here !val // evaluates to true
объяснение
это 2 оператора, a
!и--!--xИтак, это наносит ущерб x на 1 и проверяет, является ли это логическим.
если вы хотите сделать его более читабельным, можно:
var x = 1 x = x - 1 if(!x){ //=> true console.log("I understand `!--` now!") } x //=> 0попробуйте:
/* This is an example of the above, you can read this, but it is not needed for !-- */function interactive(a){$("span.code").keydown(function(e){if(13==(e.keyCode||e.which)){var t=$(this);t.clone().html("code").insertAfter(t.next().next()).show().focus().after(template.clone().removeClass("result-template").show()).next().after("<br>"),interactive(),e.preventDefault()}}).keyup(function(e){13!=(e.keyCode||e.which)&&run()})}var template=$(".result-template").hide(),code=$("span.code");code.attr("contenteditable","true").each(function(e,t){template.clone().removeClass("result-template").insertAfter(t)}),interactive(),$.fn.reduce=[].reduce;function run(){var b=!1,context={};$("span.code").each(function(){var a=$(this),res=a.next().show().removeClass("error");try{with(context)res.html(b?"":" //=> "+eval(a.text()))}catch(e){b=e,res.html(" Error: "+b.message).addClass("error")}})};run();/* This is an example of the above, you can read this, but it is not needed for !-- */span.result.error{display:block;color:red}.code{min-width:10px}body{font-family:Helvetica,sans-serif}<!-- This is an example of the above, you can read this, but it is not needed for `!--` --><span class="result result-template"> //=> unknown </span> <h2>Edit This Code:</h2><code><span class="code">x = 1</span><br><span class="code">!--x</span><br><span class="code"> x </span><br></code> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Он просто уменьшается
pendingи получает свое логическое дополнение (отрицание). Логическим дополнением любого числа, отличного от 0, являетсяfalse, для 0 этоtrue.
реальная проблема здесь заключается в отсутствии пространства между двумя операторами
!и--.я не знаю, почему люди получают это в головы, что вы никогда не можете использовать пробел после
!оператора. Я думаю, что это происходит от жесткого применения механических правил пробелов вместо здравого смысла. Почти каждый стандарт кодирования, который я видел, запрещает пробелы после всех унарных операторов, но почему?если бы был когда-нибудь случай, когда вы четко нужно это пространство, это одно.
рассмотрим следующий фрагмент кода:
if (!--pending) done(null, results);не только
!и--пюре вместе, у вас есть что(врезался в них тоже. Неудивительно, что трудно сказать, что с чем связано.немного больше пробелов делает код гораздо более ясным:
if( ! --pending ) done( null, results );конечно, если вы привыкли к механическим правилам, таким как" нет места внутри parens "и" нет места после унарного оператора", это может показаться немного чужеродным.
но посмотрите, как дополнительные пробелы группируются и отделяют различные части
ifзаявление и выражение: У вас есть--pending, так что--явно является собственным оператором и тесно связан сpending. (Он уменьшаетсяpendingи возвращает результат уменьшается.) Тогда у вас есть!отделенный от этого, так что это, очевидно, отдельный оператор, отрицающий результат. Наконец, у вас естьif(и)вокруг всего выражение, чтобы сделать егоifзаявление.и да, я убрал пробел между
ifи(, потому что(принадлежит доif. Это(не является частью какой-то(!--синтаксис, как это кажется в оригинале,(если часть синтаксис заявление.пробел здесь служит для общения смысл, вместо того, чтобы следовать некоторым механическое кодирование норматив.
Comments