Почему я не могу связать String.prototype.toLowerCase с underscore.js?

Я думаю, что проблема не в underscore.js, а в функциях собственных прототипов. Кажется, что их можно вызывать только напрямую, не передавая их как обратные вызовы. Вот код, который я не могу использовать, и ошибка из моих тестов (используя Mocha.js, только соответствующую часть):

_.chain("INPUT").tap(String.prototype.toLowerCase)
// => TypeError: String.prototype.toLowerCase called on null or undefined

Так попробовал это в REPL Node:

String.prototype.toLowerCase("INPUT")
// => ''

Я знаю, что нужно вызвать функцию прототипа с .call или же .applyа почему именно? И как я могу передать эту функцию в качестве обратного вызова?

2 ответа

Решение

Методы прототипа используют this внутренне для ссылки на объект, которым нужно манипулировать.

call а также apply позволяет вам указать this значение при вызове функции.

String.prototype.toLowerCase.call('INPUT'); //input

Если вы хотите связать this значение для функции, так что ее форма вызова не имеет значения, вы можете сделать это с _.bind или же Function.prototype.bind,

var lowerCaseInput = String.prototype.toLowerCase.bind('INPUT');

lowerCaseInput(); //input

Теперь звоню _.chain на объект обернет его в объект подчеркивания и возвращает обертку и _.tap принимает в качестве входных данных результат предыдущей функции в цепочке. Прямо здесь мы видим, что это не будет работать, так как String.prototype.toLowerCase даже не ожидает аргументов.

Не только это, но и строки являются неизменяемыми, поэтому вам придется сделать что-то вроде следующего:

_.chain({ text: 'INPUT' }).tap(function (obj) {
    obj.text = obj.text.toLowerCase();
}).value().text;

Кроме того, если вы используете миксин, вы можете использовать mixin это просто обертывания toLowerCase,

_.mixin({
    toLowerCase: function(str) {
        // Add here any desired validation if wanted
        return str.toLowerCase();
    }
}, {
    chain: false
});

После этого вы можете сделать что-то вроде:

_.chain('HELLO_WORLD')
    .toLowerCase()
    .replace('_',' ')
    .value()
Другие вопросы по тегам