Ответ 1
overloadSetter
overloadSetter
, вместе с overloadGetter
, являются двумя методами декоратора функций. Функция overloadSetter
используется для преобразования функций, которые имеют подпись fn(key, value)
для функций, которые могут принимать аргументы объекта, например: fn({key: value})
.
Чтобы сделать это, overloadSetter
должен обернуть исходную функцию. Эта функция-обертка имеет подпись fn(a, b)
, которая является ярлыком для fn(key, value)
. Это фактически становится новой перегруженной версией исходной функции.
Прежде всего, эта перегруженная функция проверяет, имеет ли переданный аргумент key
(a
) тип строки или нет. Если это не строка, функция предполагает, что мы передаем объект. Таким образом, он выполняет итерацию по каждой паре ключ-значение в объекте и применяет к ней исходную функцию. Если это строка, с другой стороны, она просто применяет эту функцию к значениям аргументов a
и b
.
Пример
Для иллюстрации предположим, что мы имеем следующую функцию:
var fnOrig = function(key, value){
console.log(key + ': ' + value);
};
var fnOver = fnOrig.overloadSetter();
fnOver('fruit', 'banana');
fnOver({'fruit': 'banana', 'vegetable': 'carrot'});
В первом вызове функция fnOver
вызывается с двумя аргументами, ключом и значением. Когда функция проверяет тип значения аргумента a
, он увидит, что это строка. Поэтому он просто вызовет исходную функцию fnOrig
: fnOrig.call(this, 'fruit', 'banana')
. Выход консоли - 'fruit: banana'
.
Для второго вызова функция fnOver
вызывается с аргументом объекта. Поскольку мы передали объект вместо строки, fnOver
будет перебирать элементы этого объекта и вызывать функцию fnOrig
для каждого из них. Таким образом, fnOrig
будет вызываться дважды в этом случае: fnOrig.call(this, 'fruit', 'banana')
и fnOrig.call(this, 'vegetable', 'carrot')
. Выход консоли - 'fruit: banana'
и 'vegetable: carrot'
.
Дополнительно
Внутри функции-обертки вы увидите, что там проверили значение usePlural
. Это аргумент для самого метода overloadSetter
. Если вы установите это значение на true
, новая функция будет обрабатывать все аргументы как объекты. Это означает, что даже если вы передадите аргумент строкового ключа, он все равно будет обрабатываться как объект.
Другое дело, что код enumerables
, который прелюбирует объявление фактического метода, существует там, потому что он исправляет проблему с некоторыми браузерами, где нативные методы Object
не перечисляются в циклах for/in
, даже если сам объект реализует его собственную версию.