Может кто нить объяснить, почему в итоге выводится информация из первого bind
, а не последнего?
function f() {
console.log(this.name);
}
f = f.bind({name: "Вася"}).bind({name: "Петя"});
f(); // Вася
Для начала заменим стандартный метод bind
на свою функцию, которая делает все то же самое. Связывает контекст
function myBind(func, thisArg) {
return (function() {
func.apply(thisArg);
});
}
function f() {
console.log(this.name);
}
f = myBind(myBind(f, {name: "Вася"}), {name: "Петя"});
// Эквивалентно следующим двум строкам
//f = myBind(f, {name: "Вася"})
//f = myBind(f, {name: "Петя"});
f();
А теперь в нашу функцию myBind
добавим логирование
function objToStr(obj) {
if (obj == window)
return "window";
else
return JSON.stringify(obj);
}
function myBind(func, thisArg, desc) {
console.log("Bind: Desc: " + desc + ", thisArg: " + objToStr(thisArg) + ", this:" + objToStr(this));
return (function() {
console.log("Call: Desc: " + desc + ", thisArg: " + objToStr(thisArg) + ", this:" + objToStr(this));
func.apply(thisArg);
});
}
function f() {
console.log(this.name);
}
f = myBind(f, {name: "Вася"}, "first")
f = myBind(f, {name: "Петя"}, "second");
console.log("After Bind");
f();
Т.е. в итоге наш вызов f()
последовательно вызывает две обертки и в конце - нашу функцию
И немного спецификации. Функция bind
возвращает так называемый exotic object - похожий на функцию, но не функцию.
У этого объекта есть три внутренних поля:
[[BoundTargetFunction]]
- ссылка на функцию, у которой вызвали bind
[[BoundThis]]
- значение this
, которое будет передаваться при вызове функции[[BoundArguments]]
- список значений, которые будут использованы как первые параметры при вызове функцииКроме того, у данного объекта переопределен метод внутренний метод Call
.
Он работает следующим образом:
[[BoundArguments]]
добавляются аргументы переданные при вызове[[BoundTargetFunction]]
с передачей в качестве this
значения поля [[BoundThis]]
и обновленного списка аргументов.Таким образом для кода
function f() {...}
var firstBind = f.bind({name: "Вася"})
var secondBind = fisrtBind.bind({name: "Петя"});
secondBind(); // Вася
вызов secondBind()
равносилен вызову firstBind.call({name: "Петя"})
, что, в свою очередь, равносильно вызову f.call({name: "Вася"})
так как при вызове экзотического объекта this
для вызываемой функции устанавливается непосредственно из его внутреннего поля.
Ответ (объяснение) же уже дан(о)! Вот здесь (или, если ближе к вопросу, то здесь).
Процитирую главное:
Первый вызов f.bind(..Вася..) возвращает «обёртку», которая устанавливает контекст для f и передаёт вызов f.
Следующий вызов bind будет устанавливать контекст уже для этой обёртки. Это ни на что не повлияет.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
этот код отвечает за вывод количества файлов, сейчас он без ограничений может выводить хоть 100 или 200 файлов, но что нужно в нем изменить что...
Как обновить элемент HelloWorld из функции updateHelloWorld и вообще это возможно?
Есть сервис который делает запрос через $http , в обработке запроса (неважно resolve или reject) , я возвращаю какие то данные через return, в итоге сервис...