Подтвердить что ты не робот

Передача в NULL в качестве параметра в ES6 не использует параметр по умолчанию, если он указан

Есть ли известная причина, по которой передача в null в качестве параметра в ES6 не использует параметр по умолчанию, если он указан?

function sayHello(name = "World") {
    console.log("Hello, " + name + "!");
}

sayHello("Jim");     // Hello, Jim!
sayHello(undefined); // Hello, World!
sayHello(null);      // Hello, null!
4b9b3361

Ответ 1

Это не так очевидно

Я прочитал несколько комментариев о том, почему undefined полностью отличается от null и почему он объясняет текущее поведение параметров по умолчанию.

Можно утверждать, что явная передача undefined не должна запускать замену значений по умолчанию, потому что когда у меня есть функция:

const f = (x = 'default') => console.log(x);

Я хотел бы, чтобы он печатал "default", когда я запускаю его как:

f();

но я бы хотел, чтобы он печатал "undefined", когда я явно запускаю его как:

f(undefined);

потому что иначе зачем использовать f(undefined) в первую очередь? Ясно, что мое намерение здесь состоит в том, чтобы предоставить некоторый аргумент, а не оставить его.

Примеры обратного

Теперь рассмотрим эту функцию:

const g = (...a) => console.log(JSON.stringify(a));

Когда я использую его как:

g();

Я получаю: []

Но когда я использую его как:

g(undefined);

Я получаю: [null]

что наглядно демонстрирует, что:

  • Передача undefined не совпадает с, поскольку не передаёт аргумент вообще
  • иногда null может быть значением по умолчанию вместо undefined

Решение TC39

Некоторые сведения о текущем поведении параметров по умолчанию можно увидеть в комментариях к собранию от 24 июля 2012 года TC39:

Кстати, это показывает, что явно передача undefined изначально не вызывала значение по умолчанию в первом черновике, и обсуждалось, следует ли это делать. Таким образом, вы можете видеть, что текущее поведение было не столь очевидным для членов TC39, поскольку теперь это похоже на тех, кто комментирует здесь.

Другие языки

Было сказано, что решение о том, что должно и что не должно вызывать замену значения по умолчанию, совершенно произвольно в конце дня. Даже наличие отдельных undefined и null может быть, хотя и довольно странным, если вы думаете об этом. Некоторые языки имеют только undefined (например, undef в Perl), некоторые из них имеют только null (например, Java), некоторые языки используют эквиваленты false или пустой список или массив для этого (например, схема, где вы можете пустой список или #f (false), но нет эквивалента null, который будет отличаться как от пустого списка, так и от ложного значения), а некоторые языки даже не имеют эквивалентов null, false или undefined (например, C, который использует целые числа вместо true и false) и указатель NULL, который на самом деле является нормальным указателем, указывающим на адрес 0, что делает этот адрес недоступным даже при сопоставлении любым кодом, который проверяет нулевые указатели).

Что вы можете сделать

Теперь я могу понять, что вам нужно заменить значения по умолчанию для null. К сожалению, это не поведение по умолчанию, но вы можете сделать простую функцию, которая поможет вам:

const N = f => (...a) => f(...a.map(v => (v === null ? undefined : v)));

Теперь каждый раз, когда вы хотите, чтобы значения по умолчанию заменялись значениями null, вы можете использовать его так. Например. если у вас есть эта функция из одного из приведенных выше примеров:

const f = (x = 'default') => console.log(x);

он напечатает "default" для f() и f(undefined), но не для f(null). Но когда вы используете функцию N, определенную выше, чтобы определить функцию f следующим образом:

const f = N((x = 'default') => console.log(x));

теперь f() и f(undefined), но также f(null) выводит "default".

Если вам нужно несколько другое поведение, например. заменяя значения по умолчанию для пустых строк - полезно для переменных среды, которые иногда могут быть установлены на пустые строки вместо не существующих, вы можете использовать:

const N = f => (...a) => f(...a.map(v => (v === '' ? undefined : v)));

Если вы хотите заменить все значения фальши, вы можете использовать его следующим образом:

const N = f => (...a) => f(...a.map(v => (v || undefined)));

Если вы хотите заменить пустые объекты, вы можете использовать:

const N = f => (...a) => f(...a.map(v => (Object.keys(v).length ? v : undefined)));

и т.д.

Заключение

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

Ответ 2

То, как параметры по умолчанию определены в спецификации. См. MDN: (выделено мной)

Параметры функции по умолчанию позволяют инициализировать формальные параметры со значениями по умолчанию, если передано no value или undefined.

null не является ни значением, ни undefined, поэтому он не запускает инициализацию по умолчанию.

Ответ 3

null - это значение, которое не будет вызывать значение по умолчанию, которое будет использоваться, значения по умолчанию будут использоваться, если аргумент undefined.