Почему метод 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?
Как проверить, содержит ли массив строку в TypeScript?