Может кто нить объяснить, почему в итоге выводится информация из первого 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 будет устанавливать контекст уже для этой обёртки. Это ни на что не повлияет.
Виртуальный выделенный сервер (VDS) становится отличным выбором
этот код отвечает за вывод количества файлов, сейчас он без ограничений может выводить хоть 100 или 200 файлов, но что нужно в нем изменить что...
Как обновить элемент HelloWorld из функции updateHelloWorld и вообще это возможно?
Есть сервис который делает запрос через $http , в обработке запроса (неважно resolve или reject) , я возвращаю какие то данные через return, в итоге сервис...