Как лучше всего определить, не отправляется ли аргумент в функцию JavaScript

Это отличный вопрос!

Давайте сосредоточимся на простой команде for на мгновение. Известная ошибка, связанная с этой командой, когда она используется для переименования файлов . Например:

set i=0
for %%a in (*.txt) do (
   set /A i+=1
   ren "%%a" !i!.txt
)

В этом случае часто некоторые файлы переименовываются дважды и даже три раза в определенных случаях. Проблема в том, что это поведение зависит от ряда факторов, которые не документированы, например, положение первого переименованного файла внутри списка исходных файлов и нескольких других точек. Аналогично, если файл удаляется до того, как он обработан for, сообщение «Файл не найден» является обычно выпущено (хотя и не ВСЕ раз). Если новый файл создается в каталоге после , запуск for начался, то он может или не может быть обработан for в зависимости (снова) от ряда факторов. Обычный способ избежать проблемы с переименованием - заставить команду for сначала прочитать весь список файлов, а , затем обработать список:

for /F "delims=" %%a in ('dir /B *.txt') do (
   set /A i+=1
   ren "%%a" !i!.txt
)

Таким образом, не имеет значения изменения, которые могут быть внесены в файлы на диске: команда for /F всегда обрабатывает список файлов оригинала .

Аналогичная проблема возникает с for /R, но в этом случае вероятность проблем больше, потому что есть больше каталогов, в которых могут быть сделаны динамические изменения. Опять же: точное поведение зависит от ряда неизвестных факторов, а способ их избежать - через for /F ... in ('dir /S /B'). Однако, если вы действительно заинтересованы в этом вопросе, я рекомендую вам провести серию тестов по этому вопросу (и опубликовать результаты). ;)

229
задан Community 23 May 2017 в 02:03
поделиться

4 ответа

Существует несколько различных способов проверить, был ли аргумент передан функции. В дополнение к двум Вы упомянули в своем (исходном) вопросе - проверка arguments.length или использование || оператор для обеспечения значений по умолчанию - можно также явно проверить аргументы в пользу undefined через argument2 === undefined или typeof argument2 === 'undefined', если Вы являетесь параноидальными (см. комментарии).

Используя || оператор стал общепринятой практикой - все спокойные дети делают это - но быть осторожными: значение по умолчанию будет инициировано, если аргумент оценит к false, что означает, что это могло бы на самом деле быть undefined, null, false, 0, '' (или что-либо еще для который Boolean(...) возвраты false).

, Таким образом, вопрос состоит в том, когда использовать, какая проверка, поскольку они все приводят к немного отличающимся результатам.

Проверка arguments.length выставки 'самое корректное' поведение, но не могло бы быть выполнимо, если существует больше чем один дополнительный аргумент.

тест для [1 116] является затем 'лучшим' - он только 'перестал работать', если функция явно вызвана с undefined значение, которое во всей вероятности нужно рассматривать тот же путь как исключение аргумента.

использование || оператор мог бы инициировать использование значения по умолчанию, даже если допустимый аргумент обеспечивается. С другой стороны, его поведение могло бы на самом деле быть желаемо.

Для суммирования: Только использование это, если Вы знаете то, что Вы делаете!

, По-моему, с помощью [1 119] также способ пойти, если существует больше чем один дополнительный аргумент, и каждый не хочет передавать литерал объектов как обходное решение для именованных параметров.

Другой хороший способ обеспечить значения по умолчанию с помощью [1 120] возможен, проваливаясь маркировки оператора переключения:

function test(requiredArg, optionalArg1, optionalArg2, optionalArg3) {
    switch(arguments.length) {
        case 1: optionalArg1 = 'default1';
        case 2: optionalArg2 = 'default2';
        case 3: optionalArg3 = 'default3';
        case 4: break;
        default: throw new Error('illegal argument count')
    }
    // do stuff
}

Это имеет оборотную сторону, что намерение программиста не (визуально) очевидно и использует 'магические числа'; это поэтому возможно подвержено ошибкам.

268
ответ дан Christoph 23 November 2019 в 03:44
поделиться

Существуют существенные различия. Давайте настроим некоторые тестовые сценарии:

var unused; // value will be undefined
Test("test1", "some value");
Test("test2");
Test("test3", unused);
Test("test4", null);
Test("test5", 0);
Test("test6", "");

С первым методом Вы описываете, только второй тест будет использовать значение по умолчанию. Второй метод примет значение по умолчанию все кроме первого (поскольку JS преобразует undefined, null, 0, и "" в булевскую переменную false. И если необходимо было использовать метод Tom, только четвертый тест будет использовать значение по умолчанию!

то, Какой метод Вы выбираете действительно, зависит от Вашего намеченного поведения. Если значения кроме undefined будут допустимы для argument2, то Вы, вероятно, захотите некоторое изменение на первом; если ненулевое, непустое, непустое значение желаемо, то второй метод идеален - действительно, это часто используется для быстрого устранения такого широкого спектра значений из рассмотрения.

7
ответ дан Shog9 23 November 2019 в 03:44
поделиться

Это - один из нескольких случаев, где я нахожу тест:

if(! argument2) {  

}

работы вполне приятно и несет корректную импликацию синтаксически.

(С одновременным ограничением, что я не позволил бы законное нулевое значение для argument2, который имеет некоторое другое значение; но это было бы действительно сбивающее с толку.)

РЕДАКТИРОВАНИЕ:

Это - действительно хороший пример стилистического различия между свободно введенными и языками со строгим контролем типов; и стилистическая опция, которую JavaScript предоставляет чрезвычайно.

Мое персональное предпочтение (без критики, предназначенной для других предпочтений), является минимализмом. Чем меньше код должен сказать, пока я последователен и краток, тем меньше кто-то еще должен постигать для корректного выведения моего значения.

Одна импликация того предпочтения - то, что я не хочу к - не находят, что оно полезный для - накапливает набор тестов зависимости типа. Вместо этого я пытаюсь сделать код средним, что похоже, что это означает; и протестируйте только на то, на что я действительно должен буду протестировать.

Одно из ухудшения, которое я нахожу в коде некоторых других народов, должно выяснить, ожидают ли они, в большем контексте, на самом деле сталкиваться со случаями, на которые они тестируют. Или если они пытаются протестировать на все возможное на шансе, что они не ожидают контекст достаточно полностью. Что означает, что я заканчиваю тем, что должен был разыскать их исчерпывающе в обоих направлениях, прежде чем я смогу уверенно осуществить рефакторинг или изменить что-либо. Я полагаю, что существует хороший шанс, они, возможно, поместили те различные тесты на месте, потому что они предвидели обстоятельства, где они будут необходимы (и которые обычно не очевидны для меня).

(я полагаю, что серьезная оборотная сторона в пути эти люди использует динамические языки. Слишком часто люди не хотят бросать все статические испытания и заканчивать тем, что фальсифицировали его.)

я видел это наиболее явно в сравнении всестороннего кода ActionScript 3 с изящным кодом JavaScript. AS3 может быть 3 или 4 раза объемом js, и надежность, которую я подозреваю, по крайней мере, не лучше, только из-за числа (3-4X) из кодирования решений, которые были приняты.

, Как Вы говорите, Shog9, YMMV.: D

13
ответ дан Nicolás Ozimica 23 November 2019 в 03:44
поделиться

Я сожалею, я все еще все же комментарий наклона, так для ответа на ответ Tom... В JavaScript (неопределенный! = пустой указатель) == ложь На самом деле, что функциональная работа привычки с "пустым указателем", необходимо использовать "неопределенный"

4
ответ дан Luca Matteis 23 November 2019 в 03:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: