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

Почему JavaScript bind() необходим?

Проблема в примере 1 - это 'this', ссылающаяся на глобальное имя вместо объекта myName.

Я понимаю использование bind() при установке значения этого для конкретного объекта, поэтому он решает проблему в примере 1, но почему эта проблема возникает в первую очередь? Это просто способ создания Javascript?

Мне также интересно, почему пример 3 решает проблему и разницу между примерами 2 и 3.

this.name = "John"

var myName = {
  name: "Tom",
  getName: function() {
    return this.name
  }
}

var storeMyName = myName.getName; // example 1
var storeMyName2 = myName.getName.bind(myName); // example 2
var storeMyName3 = myName.getName(); // example 3

console.log("example 1: " + storeMyName()); // doesn't work
console.log("example 2: " + storeMyName2()); // works
console.log("example 3: " + storeMyName3); // works
4b9b3361

Ответ 1

Почему требуется привязка JavaScript()?

Значение this определяется тем, как вызывается функция. Если вы вызываете эту функцию, обычно нет необходимости использовать .bind, так как у вас есть контроль над вызовом функции и, следовательно, ее значение this.

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

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

Другими словами: .bind позволяет вам установить значение this, не вызывая теперь функцию.

Вот сравнение ссылок на/вызывающие функции:

                    +-------------------+-------------------+
                    |                   |                   |
                    |      time of      |       time of     |
                    |function execution |    this binding   |
                    |                   |                   |
+-------------------+-------------------+-------------------+
|                   |                   |                   |
|  function object  |      future       |      future       |
|         f         |                   |                   |
|                   |                   |                   |
+-------------------+-------------------+-------------------+
|                   |                   |                   |
|   function call   |       now         |        now        |
|        f()        |                   |                   |
|                   |                   |                   |
+-------------------+-------------------+-------------------+
|                   |                   |                   |
|     f.call()      |       now         |        now        |
|     f.apply()     |                   |                   |
|                   |                   |                   |
+-------------------+-------------------+-------------------+
|                   |                   |                   |
|     f.bind()      |      future       |        now        |
|                   |                   |                   |
+-------------------+-------------------+-------------------+

Мне также интересно, почему пример 3 решает проблему и разницу между примерами 2 и 3.

Пример 1/2 и 3 не могут быть более разными. storeMyName и storeMyName2 содержат функции, которые вызываются в будущем, тогда как storeMyName3 содержит результат вызова myName.getName() в этот момент.


Дополнительный материал для чтения:

Ответ 2

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

Итак, когда вы выполняете var storeMyName = myName.getName; в первый раз, он принимает глобальный name (this.name = "John" )

Когда вы используете функцию bind(), она начинает ссылаться на имя, определенное в текущем закрытии (myName в этом случае) и, следовательно, печатает Tom

В третий раз, поскольку функция вызывается сразу, ее область видимости находится внутри своего локального объекта и, таким образом, печатает значение в закрытии Tom

Ответ 3

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

На основе вашего примера -

var storeMyName = myName.getName;

Из вышеприведенной строки вы выполняете функцию storeMyName в глобальном контексте, поэтому для этого выполнения this.name будет верхняя строка (т.е. глобальная единица/ "Джон" ).

var storeMyName2 = myName.getName.bind(myName);

Для вышеприведенной строки вы Явно меняем контекст выполнения для функции storeMyName2 (говоря, что я не хочу выполнять эту функцию как глобальную функцию, я хочу выполнить эту функцию в контексте объекта myName, поэтому в этом случае this.name будет "Tom" )

var storeMyName3 = myName.getName(); // example 3

И для этой выше строки вы просто выполняете функцию в контексте объекта myName, что более важно, вы не выполняете storeMyName3 и почему его контекст не является глобальным.

Ответ 4

Аналогию мне нравится, чего я никогда не видел: Скажем, у вас есть объект foo с функцией bar. Когда вы привязываете функцию бара к другой переменной (или передаете ее как параметр функции, что является более распространенным случаем с обратными вызовами), вы не привязываете/не передаете функцию с окружающим объектом, а только "ню". Следовательно, с помощью функции "nude" this означает глобальный объект.

Небольшая демонстрация

var foo = "global foo"; //foo set on the global object
var a = {foo : "object foo", bar : function(){return this.foo;}};
var bound = a.bar;
console.log(bound());//returns "global foo", not "object foo"

bound просто укажите на function(){return this.foo;}