Есть ли эквивалент std::bind в javascript или node.js?

Это долгий путь, но мне было интересно, есть ли такая вещь, как C++ std::bind в javascript или node.js? Вот пример, где я чувствовал потребность в привязке:

var writeResponse = function(response, result) {
    response.write(JSON.stringify(result));
    response.end();
}


app.get('/sites', function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    dbaccess.exec(query, function(result) {
        res.write(JSON.stringify(result));
        res.end();
    });
});

Вместо передачи обратного вызова в dbaccesss.exec, я хотел бы передать указатель на функцию, которая принимает один параметр. В C++ я бы передал это:

std::bind(writeResponse, res)

Это привело бы к функции, которая принимает один параметр ("результат" в моем случае), который я мог бы передать вместо анонимного обратного вызова. Прямо сейчас я дублирую весь этот код в анонимной функции для каждого маршрута в моем экспресс-приложении.

5 ответов

Решение

Пока он существует, я бы более склонен сделать это с закрытием:

function writeResponse(res) {

    return function(result) {
        res.write(JSON.stringify(result));
        res.end();
    };
}
// and then...
dbaccess.exec(query, writeResponse(res));

Если я хорошо понимаю, что вы пытаетесь сделать, я должен указать на метод Function.prototype.bind. Это работает как вы описали:

app.get('/sites', function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    dbaccess.exec(query, writeResponse.bind(null, res));
});

Хотя немного отличается от bind функция, как найдено в STL, ты можешь использовать <function>.bind, это часть прототипа функции в JavaScript.

bind метод возвращает только что созданный function объект (не забывайте, что functions являются первыми гражданами в JavaScript и создаются начиная с Function прототип), который принимает N минус M параметров (в JavaScript это действительно слабое ограничение, он всегда будет принимать столько параметров, сколько вы его передадите, но нет никаких гарантий, что они будут использованы), где N - исходное число принятых параметры, а М - связанные.

Основное отличие состоит в том, что bind принимает также в качестве первого аргумента объект области видимости, который будет доступен из вновь созданной функции как this ссылка, так что вы можете буквально изменить и ввести this ссылка во время исполнения.

Здесь вы можете найти документацию bind,

Как уже упоминалось, вы также можете положиться на замыкания, чтобы получить свою цель почти во всех случаях, когда вы можете использовать связывание.

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

app.get('/sites', function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    dbaccess.exec(query, r => writeResponse(res, r))
});

Они также сохраняют лексическое this значение, которое приятно, когда это необходимо.

Это примерно эквивалентно этому:

app.get('/sites', function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    dbaccess.exec(query, function(r) {
        return writeResponse(res, r);
    })
});

хотя этот имеет this определяется .exec(),

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

Существует также метод связывания, но он выполняет другое действие (изменяет значение this при вызове функции).

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

function currier(that, fn) {
  var args = [].slice.call(arguments, 2);

  return function() {
    return fn.apply(that, args);
  }
}
Другие вопросы по тегам