Как вы используете метод bind () без «this» в определении функции? - PullRequest
1 голос
/ 28 апреля 2019

Я довольно много читал о методе bind() и начинаю понимать, что он устанавливает this для конкретного объекта. Это почти всегда означает, что где-то в определении функции есть this, указывающее на определенный объект. Тем не менее, я видел случаи, когда bind() используется без this в определении функций. Более конкретно, this используется в качестве аргумента, что меня смущает. Например,

const eventLoader = new DataLoader((eventIds) => {
  return events(eventIds);
});

const events = async eventIds => {
  try {
    const events = await Event.find({ _id: { $in: eventIds } });
    return events.map(event => {
      return transformEvent(event);
    });
  } catch (err) {
    throw err;
  }
};

const user = async userId => {
  try {
    const user = await userLoader.load(userId.toString());
    return {
      ...user._doc,
      _id: user.id,
      createdEvents: eventLoader.load.bind(this, user._doc.createdEvents)
    };
  } catch (err) {
    throw err;
  }
};

В этом примере eventLoader.load.bind(this, user._doc.createdEvents) использует this в качестве аргумента для bind(), хотя функция eventLoader и функция events имеют this в своем определении функции. Разве это не первый аргумент bind (), в котором вы хотите, чтобы существующий this указывал на?

Ответы [ 2 ]

2 голосов
/ 28 апреля 2019

Разве это не первый аргумент bind (), в котором вы хотите, чтобы ранее существовавший объект this указывал на?

Да, точно.

В этом примере eventLoader.load.bind(this, user._doc.createdEvents) использует this в качестве аргумента для bind(), хотя функция eventLoader или функция events имеют this в своем определении функции.

Чтобы быть более точным, DataLoader.load требуется this, чтобы DataLoader работал правильно.Поэтому имеет смысл .bind eventLoader к нему eventLoader.bind(eventLoader, ...)

Привязка this не имеет смысла, так как это window (так как функция стрелки принимает контекст родительской функции², и поскольку у вас нет родительской функции [из показанного кода], родительский объект является глобальной областью действия.

¹ Читайте

² Еще большечитать

0 голосов
/ 28 апреля 2019

Первый аргумент функции bind устанавливает значение this при вызове функции.

Пример:

// You have an object
var obj = { test: "Yeah, test!" };
// We check the object properties
console.log(obj.test);

// We define a function to work with an argument
function check(myobj) {
    console.log("Is the same object?", obj === myobj);
    console.log("Is the same object?", myobj.test);
}

// Now we define a function that will work with an object as "this"
function checkthis() {
    // Notice how I use the "this" keyword, which will be the one that inherits or the one that you set
    console.log("Is the same object?", obj === this);
    console.log("Is the same object?", this.test);
}

// We call the first check
check(obj);

// Now we call the second checkthis but with another "this" context
// The first argument of call() will set the "this" context of the function and then call it instantly.
checkthis.call(obj);

// And now we are going to save another function with the this context changed.
// The first argument of bind() will also set the "this" context, but will save a reference of the function for later use, instead of calling it.
var newcheckthis = checkthis.bind(obj);

// Now we call this new function.
newcheckthis();

Обратите внимание, что newcheckthis - это функция checkthis, но с измененным контекстом this. checkthis сохранит свой контекст.

Кроме того, с помощью bind вы можете принудительно создать ссылку на функцию с помощью this. контекст изменен и заданы аргументы по умолчанию.

Пример:

// We create a function that will sum the some this object value to an argument
function sum(sumvalue) {
    return this.value + sumvalue;
}

// We create the main object
var obj = { value: 10 };

// Then we call the function setting the "this" context and passing an argument
// Note how I pass obj as the first argument and 5 as the second
// Actually it will set as the first argument (sumvalue) the second argument in the call, as the first argument in the call will be set to the "this" context. 
var result = sum.call(obj, 5);

// And we can use the same trick with bind()
var newsum = sum.bind(obj, 5);

// Now we have a newsum  function that has the this context set to "obj" and the first argument (sumvalue) set to 5 by default, which cannot be replaced.
// If we cann the function, it will di the same as the call() function above
result = newsum();

// result will still be 15.

Итак, call() и bind() (есть еще один: apply(), но работает немного по-другому) будут иметь эту подпись:

.bind/.call(THISCONTEXT, THIS_2ND_ARGUMENT_WILL_BE_THE_FIRST_ONE, 3RD_AS_SECOND, AND_SO_ON...);
...