Является ли var self = this;плохая картина? - PullRequest
74 голосов
/ 07 декабря 2010

Мне нужно:

var self = this;

много в моих классах javascript. Хотя это обычно делается, это немного не так. То, что я надеюсь найти в этом вопросе, - лучший способ справиться с этим, или что-то, чтобы убедить меня, что все в порядке.

Это стандартный способ сохранить правильные привязки? Должен ли я стандартизировать использование «себя» везде, если только мне явно не нужно «это».

edit : Я точно знаю, зачем мне это нужно, мне просто интересно, считается ли это немного злым и почему. Я знаю, что есть также встроенная функция javascript «apply» для явного определения области действия при вызове метода. Это лучше?

Ответы [ 10 ]

48 голосов
/ 07 декабря 2010

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

Тем не менее, я думаю, что вы спрашиваете (или я действительно хочу ответить):

Стоит ли ставить var self = this наверхукаждый метод / конструктор?

Резюме

Хотя я пытался сделать это один раз, и у меня возник тот же вопрос, я больше не использую этот подход.Теперь я оставляю за собой конструкцию, когда мне нужен доступ в закрытии.Для меня это добавляет немного "эй, это то, что я действительно хочу!"семантически для моего кода:

this -> this и self -> this (but really that) in a closure

Вопросы ala carte:

... Хотя это обычно делается, эточувствует себя немного не так.То, что я надеюсь найти в этом вопросе, - лучший способ справиться с этим, или что-то, чтобы убедить меня, что все в порядке.

Делайте то, что чувствует себя правильно для вас.Не бойтесь попробовать один метод и переключиться обратно позже (но, пожалуйста, старайтесь оставаться последовательными в каждом проекте: -)

Это стандартный способ сохранить правильные привязки?Должен ли я стандартизировать использование «везде» везде, кроме случаев, когда мне явно нужно «это».

«Я» - наиболее распространенное имя.Как указано выше, я предпочитаю противоположный подход - использовать this за исключением случаев, когда требуется привязка замыкания.

.., если это считается немного злым и почему.

Зло - это глупый субъективный термин (хотя иногда и забавный).Я никогда не говорил, что это зло, просто почему я не придерживаюсь подхода.Некоторые люди говорят мне, что я "злой" за то, что я не использую точки с запятой.Я говорю им, что на самом деле они должны выдвигать хорошие аргументы и / или лучше изучать JavaScript: -)

Я знаю, что есть также встроенная функция javascript 'apply' для явного определенияобласть при вызове метода.Это лучше?

Проблема с apply/call заключается в том, что вы должны использовать их в точке вызова функции.Это не поможет, если кто-то еще вызовет один из ваших методов, поскольку this может быть уже выключен.Это наиболее полезно для таких вещей, как обратные вызовы в стиле jQuery, где this является элементом / элементом обратного вызова и т. Д.

В качестве отступления ...

I хотелось бы избегать «потребности себя» в элементах и, таким образом, обычно переводить все функции-члены в свойства, в которых получатель (this) просто «протекает», что обычно «как ожидалось».

«Приватные» методы в моем коде начинаются с «_», и если пользователь вызывает их, это на них.Это также работает лучше (требуется, действительно), когда используется прототипный подход к созданию объекта.Однако Дуглас Крокфорд не согласен с моим «частным» подходом, и в некоторых случаях цепочка поиска может помешать вам, введя неожиданный получатель:

Использование границы «self» в конструкторе также блокирует верхний предел цепочки поиска для метода (он больше не полиморфен вверх!), Который может быть или не быть правильным.Я думаю, что это обычно неправильно.

Удачного кодирования.

17 голосов
/ 07 декабря 2010

Да, это стандартный способ.

Function.apply() и Function.call() могут помочь, но не всегда.

Рассмотрим следующее

function foo()
{
  var self = this;
  this.name = 'foo';

  setTimeout( function()
  {
    alert( "Hi from " + self.name );
  }, 1000 );       
}

new foo();

ЕслиВы хотели это сделать, но избегали использования такой переменной, как self и использовали вместо нее call() или apply() ... хорошо ... вы смотрите на это и начинаете пытаться, но вскоре понимаете, что просто не можете,setTimeout() отвечает за вызов лямбды, что делает невозможным использование этих альтернативных стилей вызова.Вы все равно должны создать промежуточную переменную для хранения ссылки на объект.

9 голосов
/ 07 декабря 2010

Является ли это стандартным способом сохранения правильных привязок?

Не существует стандарта в отношении систем JavaScript и классов / экземпляров.Вам нужно будет выбрать, какую модель объекта вы предпочитаете.Вот другая ссылка на фон;вывод: нет никакого заключения.

Обычно хранение копии var self= this; (*) в замыкании идет рука об руку с объектной моделью, построенной вокруг замыканий с копиями каждого метода для каждого экземпляра.Это правильный способ делать вещи;немного менее эффективный, но, как правило, немного менее трудоемкий, чем альтернатива, объектная модель, построенная на прототипировании, использующая this, bind() и пятое издание ECMAScript *1012* для получения связанных методов.

Чтоможно считать более «злым», если в одном и том же коде есть смесь обоих стилей.К сожалению, многие распространенные JS-коды делают это (потому что, давайте посмотрим правде в глаза, никто на самом деле не понимает причудливую нативную объектную модель JavaScript).

(*: я обычно использую that вместоself; вы можете использовать любое имя переменной, которое вам нравится, но self уже имеет несколько неясный и совершенно бессмысленный смысл как элемент window, указывающий на само окно.)

6 голосов
/ 09 апреля 2015

Просто наткнулся на этот вопрос, потому что мои коллеги привыкли к самому себе / этим переменным, и я хотел понять, почему ...

Я думаю, что есть лучший способ справиться с этим вв настоящее время:

function () {}.bind(this);      // native
_.bind(function () {}, this);   // lodash
$.proxy(function () {}, this);  // jquery
4 голосов
/ 07 декабря 2010

В javascript и других языках с замыканиями , это может быть очень важной вещью.Объект, на который this ссылается в методе , может фактически изменить .Если вы установите self переменную равной this, то self будет надежно оставаться ссылкой на рассматриваемый объект, даже если this позднее будет указывать на что-то другое.

Это важное различие в javascript по сравнению со многими другими языками, на которых мы работаем. Я пришел из .Net, поэтому этот тип вещей мне тоже сначала показался странным.

Редактировать А, ладно, ты все это знаешь.(возможно, все еще полезно для кого-то еще.) Я добавлю, что Apply (и Call) больше подходят для использования извне, предоставляя функции, которую вы вызываете, конкретную область, о которой вы уже знаете.Как только вы попадаете в функцию, и вы собираетесь каскадировать дальше вниз в замыкания, методика:

  var self = this;

является более подходящим способом ( easy и clear ) способ привязки вашей текущей области видимости.

2 голосов
/ 07 декабря 2010

Скорее всего, это делается для того, чтобы сохранить ссылку на this, когда область собирается измениться (в случае закрытия). Я не знаю, что я считаю это плохой практикой или моделью само по себе, нет. Подобные вещи вы часто видите в библиотеках, таких как jQuery, и много работаете с AJAX.

1 голос
/ 03 января 2017

Прошло 6 лет, и мне нужно кое-что добавить:

bind() теперь достаточно распространено, чтобы использоваться везде. Я использую это часто в качестве альтернативы. Иногда это кажется яснее. Я до сих пор иногда использую var self = this;. хотя.

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

Это:

var self = this;
var foo = function(a) {

  return self.b + a;

};

Теперь можно записать как:

var foo = a => this.b + a;

Это «наиболее оптимистичное» использование функций стрелок, но это довольно мило.

И просто для заключения, в этом нет ничего плохого:

var self = this;
1 голос
/ 10 августа 2014

Я просто хочу указать, что 'self' эквивалентно 'window', попробуйте вывести window === self на консоль. Вам следует использовать этот шаблон с 'that' или чем-то похожим в качестве имени переменной, избегайте использования 'self', поскольку он уже используется браузером (одна ошибка, и вы создадите себе глобальную переменную). Даже если это звучит странно, лучше использовать «это» в качестве имени, потому что другие разработчики сразу узнают, чего вы пытались достичь в своем коде, избегая использования нестандартных имен переменных. Я считаю, что это важная заметка, но она упоминалась только в одном комментарии, поэтому я хотел сделать ее более заметной.

1 голос
/ 21 февраля 2014

Я думаю, что есть аргумент, чтобы всегда включать var self = this в каждый метод: человеческий фактор.

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

В то же время я ловлю себя на том, что рассеянно пишу self.foo по привычке, когда мне не нужно или добавляю var self = this. Поэтому я думаю, что имеет смысл просто иметь привычку всегда включать это, нужно или нет.

Единственная проблема в том, что ... this, self или that - все это отвратительная оспа в вашем коде, и я их всех ненавижу. Поэтому я думаю, что лучше избегать использования делегированных методов, где это возможно, чтобы вы могли избегать использования this, that или self в подавляющем большинстве случаев и использовать .bind(this), когда вы могли бы в противном случае прибегнуть к self / that. Очень редко, когда использование делегатов в прототипе на самом деле сэкономит вам сколько-нибудь значительный объем памяти.

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

Как сказал Бобинс, var that = this лучше, потому что он не затеняет window.self. self = this звучит менее неловко для меня, но иногда вы получаете запутанные сообщения об ошибках, такие как property myMethod not found on global, потому что вы забыли строку self = this.

0 голосов
/ 07 декабря 2010

Мне это нравится.Это «само» - объяснительное.Дугласу Крокфорду есть, что сказать по этому поводу.Он утверждает, что использование «этого» является условием.Вы можете увидеть Крокфорда бесплатно, если вы перебегаете в yui-театр и смотрите его видео о Javascript .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...