Почему нет неявного это в JavaScript - PullRequest
14 голосов
/ 02 февраля 2011

В 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 не попадают в область действия автоматически?Я думаю, что должно быть основание для этого дизайнерского решения.

Ответы [ 6 ]

11 голосов
/ 02 февраля 2011

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

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

Создание «случайных переменных» атрибутов теневого экземпляра было бы менее опасным, но с глубоко вложенными областями, заполненными множеством имен, вы 'Вероятно, в конечном итоге он вынужден будет использовать this., так что меньше чистого выигрыша.По этой причине и / или, вероятно, по другим причинам дизайнеры сочли ярлык недопустимым.

2 голосов
/ 02 февраля 2011

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

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

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

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

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

1 голос
/ 02 февраля 2011

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

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

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

С этим было бы почти невозможно иметь дело.

1 голос
/ 02 февраля 2011

Вы должны явно указать «это», потому что вместо него «окно» неявно

Код

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

То же, что

function SomeFunc(x) {
    window.y = x;
    return this;
}
1 голос
/ 02 февраля 2011

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

function Frobber(x) { this.x = x; }
Frobber.prototype.frob = function() {
   var x = 'WHAT ABOUT ME';
   return x;
}
0 голосов
/ 02 февраля 2011

С JavaScript: Хорошие части ( Функции - вызов ):

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

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

...