Почему в JavaScript не подразумевается

В JavaScript this должен всегда указываться явно при доступе к его свойствам. Например:

function Frobber(x) {
    this.x = x;
    return this;
}

Frobber.prototype.frob = function () {
    // wrong:
    return x * x;
    // right:
    return this.x * this.x;
}

Я знаю, что могу использовать with(this) (который устарел и вообще не одобряется), но почему не являются свойствами this в области автоматически? Я думаю, что для принятия такого конструктивного решения должна быть причина.

Ответ 1

Это похоже на Python. Причина довольно проста: вы не можете добавить это, потому что он сталкивается с правилом определения области поиска для поиска нелокальных переменных во внешних областях. Это возможно в статически типизированных языках, поскольку члены this известны во время компиляции.

И что, если это сделало это динамическое решение, например, "x относится к this.x, если this.x !== undefined и в противном случае к переменной x" (или любое другое правило для этого, которое определено во время выполнения)? Это очень опасно, поскольку он может теневать локальные переменные, основанные на том, что this происходит, то есть разбивает совершенно допустимый код только для определенных объектов. Другая проблема: должен ли undeclaredVar = ... добавить новый атрибут экземпляра? Если нет, это будет уродливая асимметрия между неявным и явным this. Если он создает атрибут экземпляра, вы потеряете возможность устанавливать глобальную и замыкающую переменную изнутри функций - не слишком много потерь, многие скажут; но разработчики JS, похоже, думали иначе, поскольку по умолчанию они выбрали глобальную область.

Создание атрибутов теневого экземпляра "случайные переменные" было бы менее опасным, но с глубоко вложенными областями, заполненными множеством имен, в большинстве случаев вы были бы вынуждены использовать this., поэтому меньшее количество выигрышей в сети, Для этого и/или возможно по другим причинам дизайнеры считали, что сокращение невозможно.

Ответ 2

Что означает "this" в Javascript, является полностью функцией того, как была вызвана текущая функция.

Если он вызывается как метод (т.е. с оператором.), то 'this' будет установлен в объект перед точкой.

Если он вызывается как простая функция, то 'this' будет глобальным объектом (обычно это окно).

IIRC, если вы используете Function.call, вы можете установить его явно.

Javascript - это язык OO, но не имеет классов и не имеет (строго) методов.

Ответ 3

Если x подразумевается как this.x, как бы вы обращались к переменным, определенным как имя x?

function Frobber(x) { this.x = x; }
Frobber.prototype.frob = function() {
   var x = 'WHAT ABOUT ME';
   return x;
}

Ответ 4

Вы должны явно указать "this", потому что вместо этого "window" подразумевается

код

function SomeFunc(x) {
    y = x;
    return this;
}

То же, что и

function SomeFunc(x) {
    window.y = x;
    return this;
}

Ответ 5

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

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

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

С этим было бы почти невозможно справиться.

Ответ 6

От JavaScript: Хорошие части (Функции - Invocation):

В JavaScript существует четыре шаблона вызова: шаблон вызова метода, шаблон вызова функции, шаблон вызова конструктора и шаблон обращения приложения.

В принципе, каждый из этих "шаблонов" определяет способ определения ссылки this. Если функция определена как метод объекта, this будет ссылаться на родительский объект. Если функция не является свойством объекта, this относится к глобальному объекту. Если функция вызывается с ключевым словом new (т.е. Как конструктор), то this относится к вновь созданному объекту. И, наконец, если вы используете функцию apply(), ссылка this привязана к любому объекту, который вы указали.