Опубликован: 23.12.2005 | Уровень: специалист | Доступ: платный | ВУЗ: Московский физико-технический институт
Лекция 6:

Классы

Методы и свойства в прототипе

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

Добавляем методы в прототип

Итак, открываем новый Флэш-файл и пишем там вот что:

// Конструктор
_global.lift = function (minFloor, maxFloor){
		// Проверяем, не перепутал ли пользователь максимальный 
		// и минимальный этажи
	if (minFloor < maxFloor){
		this.minFloor = Math.round(minFloor);
		this.maxFloor = Math.round(maxFloor);
	}
	else{  // Если перепутал, корректируем
		this.minFloor = Math.round(maxFloor);
		this.maxFloor = Math.round(minFloor);
	}
	// Устанавливаем лифт на 1 этаж (но если лифт туда не должен
	// ездить, корректируем начальный этаж в нужную сторону).
	this.currentFloor = Math.min(Math.max(1, this.minFloor), this.maxFloor);
	this.doorsAreOpen = true; 
}
	// Функции - те же, что и раньше, но размещаем их в прототипе
_global.lift.prototype.goto = function(where){
	trace("-----------");
		// Oкругляем и ограничиваем этаж назначения
	this.floorToGo = Math.min(Math.max(Math.round(where), 
		this.minFloor), this.maxFloor);
	if (this.floorToGo != this.currentFloor) this.go();//Поехали!
	else trace("Ничего не делаем." );
	trace("-----------");
}
_global.lift.prototype.setDoorsOpen = function(open){
	if (this.doorsAreOpen != open){
		trace(open ? "Открываем двери." : "Закрываем двери.")	
	}
	this.doorsAreOpen = open;
}
_global.lift.prototype.go = function(){
	this.setDoorsOpen(false);
	var distance = this.floorToGo - this.currentFloor;
	var signOfDistance = (distance >= 0 ? 1 : -1);
	for(  // Это работает независимо от того, едем вверх или вниз
		var i = this.currentFloor; 
		signOfDistance*i <= signOfDistance*this.floorToGo; 
		i += signOfDistance
	){
		trace("Этаж " + i);
		this.currentFloor = i;
	}
	this.setDoorsOpen(true);
}
  // Создаем 2 объекта
l1 = new lift(2, 5);
l2 = new lift(0, 3);
  // Тестируем 
trace("l1:");
l1.goto(4);
trace("l2:")
l2.goto(4);

На выходе получаем:

l1:
-----------
Закрываем двери.
Этаж 2
Этаж 3
Этаж 4
Открываем двери.
-----------
l2:
-----------
Закрываем двери.
Этаж 1
Этаж 2
Этаж 3
Открываем двери.
-----------

Теперь, как видно, мы можем писать не new _global.lift, а просто new lift, поскольку объект по имени lift мы не создавали, а сразу разместили все нужные методы в поле prototype функции- конструктора. Также видно, что переработка конструктора дала свои плоды: лифт номер 1 поехал на четвертый этаж со второго, а не с первого, поскольку ниже второго этажа он спускаться не может.

Нужно ли добавлять поля в прототип

Мы можем добавить в прототип не только методы, но и поля. Те значения, которые мы установим для этих полей в прототипе, будут автоматически скопированы во все экземпляры классов. (Точнее, так будет казаться на первый взгляд, до тех пор, пока мы не разберемся в механизме copy-on-write.) Таким способом имеет смысл устанавливать значения полей по умолчанию или же значения констант. Если же значение поля в любом случае устанавливается в конструкторе, то можно обойтись и без помещения поля в прототип. В случае нашего лифта мы могли бы поместить в прототип поле doorsAreOpen и присвоить ему там значение true. Это соответствовало бы тому факту, что лифты нашей конструкции после монтажа стоят с открытыми дверьми.

алексеи федорович
алексеи федорович
Беларусь, рогачёв
Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009