Skip to content

Instantly share code, notes, and snippets.

@subzey
Last active December 6, 2017 14:16
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save subzey/8115612 to your computer and use it in GitHub Desktop.
Save subzey/8115612 to your computer and use it in GitHub Desktop.
Про это

Про это

Как вы называете переменную, когда нужно сохранить this в замыкании?

Вопрос не праздный, ведь это дело даже не личного вкуса, а, скорее, договоренности. В коде проекта, над которым я сейчас активно работаю, можно было с равной степенью вероятности встретить that и self. Через два года разработки, впрочем, баланс заметно сместился в сторону that.

Но знаете, что? И self, и that, и даже _this с me — это очень хреновые названия.

Почему?

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

function MulberryPlucker() {}
MulberryPlucker.prototype.pluckedMulberry = null;
MulberryPlucker.prototype.pluck = function() {
	var that = this;
	var asyncPlucker = new AsyncPlucker('mulberry');
	asyncPlucker.pluck(function(mulberry) {
		that.pluckedMulberry = mulberry;
	});
}

Вы можете сказать, это такое? В смысле, что означает that? Пока что да, хорошо, а так?

function MulberryPlucker() {}
MulberryPlucker.prototype.pluckedMulberry = null;
MulberryPlucker.prototype.pluck = function() {
	var that = this;
	AsyncPluckerAsyncFactory.createPlucker(function(asyncPlucker) {
		asyncPlucker.onreadystatechange = function() {
			if (asyncPlucker.readyState === asyncPlucker.STATE_READY) {
				asyncPlucker.pluck(function(mulberry) {
					if (typeof GlobalNotifier !== 'undefined'){
						GlobalNotifier.notifyNewMulberry(mulberry);
					}
					that.pluckedMulberry = mulberry;
				});
			}
		}
		asyncPlucker.setTypeAsync('mulberry');
	})
}

Уже сложнее. А если добавить ещё десяток уровней вложенности и кода экрана два? Или так: в рабочий чатик прилетает сообщение, мол, а что делает эта функция?

function(mulberry) {
	that.pluckedMulberry = mulberry;
}

Вы сможете ответить точно и сразу?

Увы, это реальность, код не находится в кристально чистом состоянии, и не всегда код, который мы поддерживаем — это код, который мы писали. И чтобы как-то сгладить эффекты этой самой реальности мы, программисты, называем переменные понятными именами. Так почему же, чёрт возьми, не делать то же самое с this.

А как же?

А очень просто. Точно так же, как конструктор, только с маленькой буквы. Т.е., если this представляет собой инстанс EvilDestructionWidget, то его имеет смысл обозвать evilDestructionWidget.

И код чудесным образом становится более понятным:

function MulberryPlucker() {}
MulberryPlucker.prototype.pluckedMulberry = null;
MulberryPlucker.prototype.pluck = function() {
	var mulberryPlucker = this;
	var asyncPlucker = new AsyncPlucker('mulberry');
	asyncPlucker.pluck(function(mulberry) {
		mulberryPlucker.pluckedMulberry = mulberry;
	});
}

Ну, разве не красота?

Но…

Что, даже в микроскопическом методе?

Да. Везде. Это всегда так, «ой, у меня всего-лишь маленький скриптик, пусть всё будет валяться в глобале…», и чем это заканчивается?

Это же увеличит размер js-файла

А вы разве не минифицируете скрипты? Очень советую. Тем более, что такие переменные обычно не «торчат» наружу и прекрасно переименовываются минификатором во что-нибудь однобуквенное.

Ладно… мне просто лениво печатать.

Я вас умоляю. Вы знаете, как работает this, что такое замыкание, и пишете код в notepad.exe? Наверняка ваш редактор умеет делать подстановку.

Имя конструктора и так начинается с маленькой буквы

А зря. Переименуйте везде на большую и не позорьтесь.

Мой конструктор называется That

Ладно, тогда можно. Но вы в курсе, это отвратительное имя для конструктора.

@ptmt
Copy link

ptmt commented May 24, 2015

В 2015 как минимум:

class MulberryPlucker {
   constructor() {
       this.pluckedMulberry = null
   }
   pluck() {
      let asyncPlucker = new AsyncPlucker('mulberry')
      asyncPlucker.pluck(mulberry => this.pluckedMulberry = mulberry)
   }
}

@felixexter
Copy link

Долгое время использовали _this, но этот гист заставил задуматься и стандартизировать это 😄

@kinday
Copy link

kinday commented May 24, 2015

@felixexter, привет. (:

Красиво и понятно, я за стандартизацию.

@listochkin
Copy link

Мне кажется, что идея не самая лучшая.

  1. Программисты ожидают, что эта переменная будет называться self, that или _this. Некоторые стайлгайды даже закрепляют одно из этих названий. Видеть незнакомую переменную в такой роли будет запутывать других разработчиков.

  2. Практика подобных названий закрепилась во времена, когда в браузерах по умолчанию не было родной реализации Function.prototype.bind. Сегодня, когда она у нас есть, лучшее название для this - это this:

    doSomething(function (param, pamPam) {
      this.doSomethinElse(pamPam);
    }.bind(this));
  3. С ES6, который при помощи транспайлеров можно смело использовать уже несколько лет как, проблема решается еще проще, как выше показал @unknownexception

@VovanR
Copy link

VovanR commented May 24, 2015

Надо будет попробовать на новом небольшом проекте, чтобы понять насколько это может быть неудобно для команды.
Так, например, во всяких сниппетах, шаблонах и скафолдерах уже забито _this.

@avevlad
Copy link

avevlad commented May 24, 2015

revised this gist on 25 Dec 2013
а щас 2015 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment