Класс JavaScript и контекст вызова - PullRequest
4 голосов
/ 18 января 2012

Может кто-нибудь помочь мне объяснить, почему первый пример работает, а второй нет.

Пример 1:

// Define a class
function Foo(name) {
  var self = this;

  this.name = name;
  this.greeting = function() {
    console.log('Hello ' + self.name);
  }
}

var foo = new Foo('foo');
foo.greeting();

var greeting = foo.greeting;
greeting();

Вывод:

Hello foo
Hello foo

Пример 2:

// Define a class
function Foo(name) {
  this.name = name;
}

// Greeting
Foo.prototype.greeting= function () {
  console.log('Hello ' + this.name);
}

var foo = new Foo('foo');
foo.greeting();

var greeting = foo.greeting;
greeting();

Вывод:

Hello foo
Hello undefined

Я полагаю, что в первом примере используется замыкание, поэтому он сохраняет ссылку на локальную переменную name, ноВторой пример - нет, и поскольку метод greeting() вызывается без контекста объекта, по умолчанию используется undefined.

Ответы [ 4 ]

6 голосов
/ 18 января 2012

Множество ответов, все с полезной и правильной информацией, но ни один из них не объясняет правильное поведение.

В вашем первом примере он регистрирует только Hello foo оба раза, поскольку вы создаете переменную self, который ссылается на объект this.Эта переменная self затем закрывается в вашем greeting function.Следовательно, вы можете вызывать эту функцию так, как хотите, она всегда будет обращаться к self.name, а не к this.name, поэтому она всегда одинакова.

Вы не делаете этого в своем примере prototype.Там вы непосредственно получаете доступ к this.name, и тогда действительно важно, как вызывается функция (см. Ответ @lwburk).

Опять же, даже если вы называете первый пример как1018 *

foo.greeting.call( window );

он все равно будет обращаться к закрытой переменной self и журналу Hello foo.

5 голосов
/ 18 января 2012

Существует четыре способа вызова функции в JavaScript, каждый из которых изменяет значение this внутри функции:

  1. Как глобальная функция Звоните: greeting().Значение this является глобальным window объектом (в браузерах).

  2. Как метод для некоторого объекта: foo.greeting().Значение this является экземпляром объекта в левой части оператора . (foo).

  3. в качестве конструктора :new greeting().Значение this - это новый объект, который создается и неявно возвращается из функции.Используется для создания новых объектов.

  4. Использование call или apply: greeting.apply(someVal, someArgs).Значение this - это объект, переданный в качестве первого аргумента (someVal).

Любая функция может быть выполнена любым из этих четырех способов (хотя не все функции * 1044).* в некоторых из них должно быть выполнено).

В первом случае вы выполняете вызов метода:

var foo = new Foo('foo');
foo.greeting();

... поэтому this равно foo внутри функции.Во втором случае вы выполняете глобальный вызов функции:

var greeting = foo.greeting;
greeting();

... поэтому this это window внутри функции.

Редактировать: Обратите внимание на ответ @ jAndy, который указывает на более существенную проблему в этом случае, которая заключается в том, что greeting закрывается над self в первом примере (независимо от того, как это называется), но не во втором (что затем делает как функция называется актуальной).

2 голосов
/ 18 января 2012

Разрешение this задерживается до времени выполнения в JavaScript.

Установив foo.greeting на greeting, а затем выполнив greeting(), вы выполняете greeting() в глобальном контексте; в котором this указывает на window, если вы не работаете в строгом режиме , а не в своем экземпляре Foo. Из-за этого внутри greeting() он ищет window.name; и возвращение undefined.

Более подробное объяснение см. this в MDC .

0 голосов
/ 18 января 2012

второе приветствие () выполняется в глобальной области видимости, поэтому соответственно this является объектом окна (та же область, в которой выполняется функция, и тогда window.name не определена) Он снова работает, если вы передаете контекст через apply() или call(), например.

var greeting = foo.greeting;
greeting.apply(foo);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...