Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык JavaScript часть1.pdf
Скачиваний:
189
Добавлен:
22.03.2016
Размер:
8.92 Mб
Скачать

Добавить функциям defer с аргументами

важность: 4

Добавьте всем функциям в прототип метод defer(ms), который возвращает обёртку, откладывающую вызов функции на ms миллисекунд.

Например, должно работать так:

function f(a, b) { alert( a + b );

}

f.defer(1000)(1, 2); // выведет 3 через 1 секунду.

То есть, должны корректно передаваться аргументы.

К решению

Свои классы на прототипах

Используем ту же структуру, что JavaScript использует внутри себя, для объявления своих классов.

Обычный конструктор

Вспомним, как мы объявляли классы ранее.

Например, этот код задаёт класс Animalв функциональном стиле, без всяких прототипов:

function Animal(name) { this.speed = 0; this.name = name;

this.run = function(speed) { this.speed += speed;

alert( this.name + ' бежит, скорость ' + this.speed ); };

this.stop = function() { this.speed = 0;

alert( this.name + ' стоит' ); };

};

var animal = new Animal('Зверь');

alert( animal.speed ); // 0, начальная скорость animal.run(3); // Зверь бежит, скорость 3 animal.run(10); // Зверь бежит, скорость 13 animal.stop(); // Зверь стоит

Класс через прототип

А теперь создадим аналогичный класс, используя прототипы, наподобие того, как сделаны классы

Object, Dateи остальные.

Чтобы объявить свой класс, нужно:

1.Объявить функцию-конструктор.

2.Записать методы и свойства, нужные всем объектам класса, в prototype.

Опишем класс Animal:

//конструктор function Animal(name) {

this.name = name; this.speed = 0;

}

//методы в прототипе

Animal.prototype.run = function(speed) { this.speed += speed;

alert( this.name + ' бежит, скорость ' + this.speed ); };

Animal.prototype.stop = function() { this.speed = 0;

alert( this.name + ' стоит' ); };

var animal = new Animal('Зверь');

alert( animal.speed ); // 0, свойство взято из прототипа animal.run(5); // Зверь бежит, скорость 5 animal.run(5); // Зверь бежит, скорость 10 animal.stop(); // Зверь стоит

В объекте animalбудут хранится свойства конкретного экземпляра: nameи speed, а общие методы — в прототипе.

Совершенно такой же подход, как и для встроенных классов в JavaScript.

Сравнение

Чем такое задание класса лучше и хуже функционального стиля?

Достоинства

Функциональный стиль записывает в каждый объект и свойства и методы, а прототипный — только свойства.

Поэтому прототипный стиль — быстрее и экономнее по памяти.

Недостатки

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

Таким образом, прототипный стиль — быстрее и экономнее, но немного менее удобен.

К примеру, есть у нас приватное свойство nameи метод sayHiв функциональном стиле ООП:

function Animal(name) { this.sayHi = function() {

alert( name ); };

}

var animal = new Animal("Зверь"); animal.sayHi(); // Зверь

При задании методов в прототипе мы не сможем её так оставить, ведь методы находятся вне конструктора, у них нет общей области видимости, поэтому приходится записывать nameв сам

объект, обозначив его как защищённое:

function Animal(name) { this._name = name;

}

Animal.prototype.sayHi = function() { alert( this._name );

}

var animal = new Animal("Зверь"); animal.sayHi(); // Зверь

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

Задачи

Перепишите в виде класса

важность: 5

Есть класс CoffeeMachine, заданный в функциональном стиле.

Задача: переписать CoffeeMachineв виде класса с использованием прототипа.

Исходный код:

function CoffeeMachine(power) { var waterAmount = 0;

var WATER_HEAT_CAPACITY = 4200;

function getTimeToBoil() {

return waterAmount * WATER_HEAT_CAPACITY * 80 / power;

}

this.run = function() { setTimeout(function() {

alert( 'Кофе готов!' ); }, getTimeToBoil());

};

this.setWaterAmount = function(amount) { waterAmount = amount;

};

}

var coffeeMachine = new CoffeeMachine(10000); coffeeMachine.setWaterAmount(50); coffeeMachine.run();

P.S. При описании через прототипы локальные переменные недоступны методам, поэтому нужно будет переделать их в защищённые свойства.

К решению

Хомяки с __proto__

важность: 5

Вы — руководитель команды, которая разрабатывает игру, хомяковую ферму. Один из программистов получил задание создать класс «хомяк» (англ – "Hamster").

Объекты-хомяки должны иметь массив foodдля хранения еды и метод found, который добавляет к нему.

Ниже — его решение. При создании двух хомяков, если поел один — почему-то сытым становится и второй тоже.

В чём дело? Как поправить?