Muranx
@Muranx
кто понял this тот в цирке не смеётся

Почему данном случае теряется контекст this?

Здравствуйте !

Function.prototype.anyMeth=function(obj){
  fn=this // ((1))
  document.write(fn.name+"<br>") // просто для проверки того, на что указывает в данном случае this
      return function(){ // ((2))
          document.write(this+"<br>") // ((3))
          return fn.call(!this ? this : obj) // ((4))
      }
};

var a="Привязка к глобальному объекту по умолчанию",
    b={a:"Свойство 'а' из объекта b"},
    c={a:"Свойство 'а' из объекта с"}

function back(){
  document.write(this.a);
};

var hoj = back.anyMeth();

hoj(c);

1) Почему в возвращаемой функции ((2)) теряется тот this который был в ((1)), разве при вызове ((3)) интерпритатор не должен искать this выше в коде?(или это работает только с замыканиями, а на зыс это не распространяется) Не понимаю как получается, что находясь в скоупе Function.prototype.anyMeth=function(obj), this указывает на объект (на функцию) из которой будет вызываться метод anyMeth, но в возвращаемой из этого скоупа функции мы теряем этот this, в строке ((3))это и есть та самая потеря контекста и возврат к привязке по умолчанию, тоесть объекту window, или как?

2) Как абсолютно буквально, не тривиально, без талых шуток програмистов, и намеренного запутывания моего неокрепшего в програмировании ума расписать эту конструкцию под номером ((4))?
Мы вызываем функцию fn и должны ей передать контекст вызова, т.е. передать некий объект, так что данное условие проверяет? я не понимаю саму структуру (!this ? this : obj) т.е. переданный объект проверяется на присутствие в коде? Т.к. к примеру если передать объект c результат будет true НО у нас же !this поэтому вернётся false в виду чего сработает вызов obj (согласно условию), НО obj ЖЕ У НАС объект c, так каким образом возвращается привязка по умолчанию, т.е. this указывает на виндовс? (что мы собственно и видим, если вставить код в тот-же codepen)

Проблема в том, что фраза "зыс определяется не там где объявленна функция, а там где вызывается" сбивает меня с толку, в случаях типо fn.call(!this ? this : obj) (т.к. функция эта вызывается внутри другой функции, у которой свой this внутри, но при этом она обозначает не этот зыс), вообщем спасибо заранее за ответ!
  • Вопрос задан
  • 150 просмотров
Решения вопроса 1
Aetae
@Aetae Куратор тега JavaScript
Тлен
Простой ответ:
Берём метод:
метод = function(){
  console.log(this)
};
и(не важно как) пихаем его в какие-то объекты.
Получаем:
хрень.метод() // this - хрень
хрень.кишки.метод() // this - хрень.кишки
метод() // this - window

хрень.метод.call(хрень.кишки) // this - хрень.кишки
метод.call(хрень.кишки) // this - хрень.кишки
метод.call(null) // this - null

элемент.addEventListener('оппа', хрень.метод) //  this -элемент
элемент.addEventListener('оппа', метод) //  this -элемент
элемент.addEventListener('оппа', хрень.кишки.продукт.метод) //  this -элемент

По сути this для фукции - это то, что идёт перед точкой, кроме тех случаев когда он переопределён явно. Всё, никакой эзотерики.)

fn.call(!this ? this : obj) - это чушь скорее всего. Если this - falsy, то ставим его как this при вызове функции fn, иначе ставим obj. Falsy this может быть только при явном указании(или в strict режиме, при вызове функции напрямую("без точки перед ней")), и скорее всего передача пустого this в таком случае просто сломает выполнение fn.

Ну ещё следует упомянуть стрелочную фукнцию:
метод = () => {
  console.log(this)
};
это можно считать за явное указание this, потому что this тут всегда привязан тот, что был при создании стрелочной функции, независимо от того как и откуда её вызывают.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы