к 'этому' объекту нельзя получить доступ в частных функциях JavaScript без взлома?

Я работал над проектом некоторое время, пытаясь выяснить то, что я делал неправильно, когда я наконец сузил "ошибку" к тому, которое ниже кода не работает, как я ожидал:

function Alpha()
    {
    this.onion = 'onion';

    function Beta()
        {
        alert(this.onion);
        }

    Beta();
    }

alpha1 = new Alpha();
// Alerts 'undefined'

Однако, если я изменяю код на это:

function Alpha()
    {
    var self = this;
    this.onion = 'onion';

    function Beta()
        {
        alert(self.onion);
        }

    Beta();
    }

alpha1 = new Alpha();
// Alerts 'onion'

это работает как, я ожидал бы. После траты значительной части моей жизни кто-либо может объяснить, почему она работает как это?

7
задан Nick 18 July 2010 в 04:59
поделиться

3 ответа

Работает так, потому что каждая функция связана со своим собственным контекстом выполнения .

Однако есть и другие способы сделать это, например:

Использование call или apply для вызова функции:

function Alpha() {
  this.onion = 'onion';

  function Beta() {
    alert(this.onion);
  }

  Beta.call(this);
}

var alpha1 = new Alpha();
// Alerts 'onion'

Новый стандарт ECMAScript 5th Edition представляет способ сохранить функцию context , метод Function.prototype.bind :

function Alpha() {
  this.onion = 'onion';

  var Beta = function () {
    alert(this.onion);
  }.bind(this);

  Beta();
}

var alpha1 = new Alpha();
// Alerts 'onion'

Мы можем сказать, что функция Beta привязана , и независимо от того, как вы его вызываете, его значение this будет неизменным.

Этот метод еще не получил широкой поддержки, в настоящее время только IE9pre3 включает его, но вы можете включить реализацию , чтобы он работал сейчас.

Теперь позвольте мне подробнее рассказать о том, как this работает:

Значение this существует в каждом контексте выполнения , а для кода функции устанавливается неявно, когда выполняется вызов функции, значение определяется в зависимости от того, как формируется ссылка .

В вашем примере, когда вы вызываете Beta (); , поскольку он не привязан ни к какому объекту, мы можем сказать, что ссылка не имеет базового объекта , тогда это значение будет относиться к глобальному объекту.

Другой случай возникает, когда вы вызываете функцию, которая связана как свойство объекта, например:

var obj = {
  foo: function () { return this === obj;}
};
obj.foo(); // true

Как видите, вызываемая ссылка obj.bar (); содержит базовый объект, которым является obj , и значение this внутри вызываемой функции будет ссылаться на него.

Примечание : ссылочный тип является абстрактным понятием, определенным для целей языковой реализации, подробности можно увидеть в спецификации.

Третий случай, когда значение this устанавливается неявно, - это когда вы используете оператор new , он будет ссылаться на вновь созданный объект, который наследуется от прототипа своего конструктора:

function Foo () {
  return this; // `this` is implicitly returned when a function is called 
}              // with `new`, this line is included only to make it obvious

var foo = new Foo();
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
10
ответ дан 6 December 2019 в 09:57
поделиться

Когда вы вызываете функцию, не являющуюся членом (не вызываемую как someObject.method () ), она запускается в контексте окна. Неважно, частная это функция или глобальная.

Вы можете сделать:

Beta.call(this);

call позволяет вам вызывать функцию, передавая контекст в качестве первого аргумента ( apply аналогичен, но список аргументов является массивом).

Однако мне непонятно (даже для простейшего примера), почему луковица является общедоступной, а бета-версия - частной.

2
ответ дан 6 December 2019 в 09:57
поделиться

Из JavaScript: Полное руководство, 5-е издание (книга rhino):

Когда функция вызывается как функция, а не метод, это ключевое слово относится к глобальному объект. Как ни странно, это правда даже когда вызывается вложенная функция (как функция) внутри содержащего метода который был вызван как метод: this ключевое слово имеет одно значение в содержащий функцию, но (парадоксально) относится к глобальный объект в теле вложенная функция.

Обратите внимание, что this является ключевым словом, а не имя переменной или свойства. JavaScript синтаксис не позволяет назначить значение это .

Здесь следует обратить внимание на две вещи:

  1. this не является переменной, поэтому обычные правила захвата закрытия не применяются.
  2. this является «отскоком» при каждом вызове функции, будь то метод, обычный вызов функции или через new . Поскольку вы выполняете обычный вызов функции (при вызове бета-версии), this привязывается к «глобальному объекту».
7
ответ дан 6 December 2019 в 09:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: