Почему метод bind() в JavaScript необходим?
Проблема в примере 1 заключается в том, что 'this' ссылается на глобальный объект, а не на объект myName.
Я понимаю, как использовать метод bind() для привязки значения this к определенному объекту, и это решает проблему в примере 1. Но почему эта проблема возникает изначально? Это просто особенность JavaScript?
Кроме того, меня интересует, почему пример 3 решает эту проблему, и в чем разница между примером 2 и примером 3.
Вот код для наглядности:
this.name = "John";
var myName = {
name: "Tom",
getName: function() {
return this.name;
}
}
var storeMyName = myName.getName; // пример 1
var storeMyName2 = myName.getName.bind(myName); // пример 2
var storeMyName3 = myName.getName(); // пример 3
console.log("пример 1: " + storeMyName()); // не работает
console.log("пример 2: " + storeMyName2()); // работает
console.log("пример 3: " + storeMyName3); // работает
Почему в первом примере возникает проблема с 'this', и как именно примеры 2 и 3 по-разному решают эту проблему?
2 ответ(ов)
Вопрос, который вы поднимаете, касается контекста this в JavaScript. Ваше аналогия очень наглядная и помогает понять, как работает привязка функций.
Когда вы определяете объект a с методом bar, этот метод, по сути, относится к объекту a, и в нем this ссылается на a. Однако, когда вы присваиваете a.bar переменной bound, вы фактически создаете ссылку на функцию bar без ее окружения. В результате, при вызове bound(), this становится глобальным объектом (или undefined в строгом режиме), что и приводит к получению "global foo".
Вот ваш пример:
var foo = "global foo"; // foo определен в глобальном контексте
var a = {
foo: "object foo",
bar: function() {
return this.foo; // Здесь `this` ссылается на объект `a`
}
};
var bound = a.bar; // Мы просто ссылаемся на функцию без контекста
console.log(bound()); // Вернет "global foo", а не "object foo"
Чтобы сохранить правильный контекст this, вы можете использовать метод bind, который создает новую функцию с заданным значением this. Например:
var boundWithContext = a.bar.bind(a);
console.log(boundWithContext()); // Теперь вернет "object foo"
Таким образом, использование bind, а также такие методы, как call или apply, позволяет контролировать контекст выполнения функции, что часто бывает необходимо при работе с колбэками или передаче функций в качестве аргументов.
bind — это механизм, который позволяет изменить контекст выполнения функции (в данном случае ваш текущий контекст по умолчанию — глобальный).
Основываясь на вашем примере:
var storeMyName = myName.getName;
В этой строке вы вызываете функцию storeMyName в глобальном контексте, поэтому в этом случае this.name будет ссылаться на верхний уровень (т.е. глобальный контекст / "John").
var storeMyName2 = myName.getName.bind(myName);
В этой строке вы явно изменяете контекст выполнения функции storeMyName2 (говоря, что не хотите выполнять эту функцию в глобальном контексте, а хотите использовать контекст объекта myName, так что в этом случае this.name будет равно "Tom").
var storeMyName3 = myName.getName(); // пример 3
А в этой строке вы просто вызываете функцию в контексте объекта myName, более того, вы не выполняете storeMyName3, и именно поэтому её контекст не является глобальным.
Как получить правильный `this` внутри колбэка?
Как работает ключевое слово "this" и когда его следует использовать?
jQuery событие Keypress: Как узнать, какая клавиша была нажата?
Использование 'prototype' и 'this' в JavaScript?
Где найти документацию по форматированию даты в JavaScript?