функция позволяет вызывать одну функцию из контекста другой, т.е. мы можем определить, как действует ключевое слово this. С помощью call можно написать класс Animal (Животное), а затем вызвать его из класса Cat или Dog.

function Animal(name){

this.name = name;

this.species = 'Animal';

this.sleep = function(){ alert(this.name+' спит: Хрррр'); }

}

function Cat(name){

Animal.call(this, name);

this.talk = function(){ alert('Мяу!'); }

}

function Dog(name){

Animal.call(this, name);

this.talk = function(){ alert('Гав!'); }

}

var sam = new Cat('Sam');

var joe = new Dog('Joe');

sam.sleep(); // Sam спит: Хрррр

joe.sleep(); // Joe спит: Хрррр

sam.talk(); // Мяу!

joe.talk(); // Гав!

Хотя это работает, мы немного ограничены в своих возможностях. Например, прототипирование не действует при использовании этого метода: все прототипы, заданные на Animal, не будут переноситься в функции Cat или Dog. Как мы знаем из предыдущей лекции, определенные внутренне с помощью 'this.' функции создают новый экземпляр всякий раз при создании новой копии предка. В этом случае всякий раз при создании функции Animal, Cat или Dog появляется новая копия функций species и sleep. Как можно догадаться, это не самый эффективный способ.

Лучшим подходом является прототипирование всего родительского класса на классе-потомке. Это предоставляет доступ ко всем свойствам и методам класса предка:

function Animal(name){

this.name = name;

}

Animal.prototype = {

species: 'Animal',

sleep : function(){ alert(this.name+' спит: Хрррр'); }

}

function Cat(name){

Animal.apply(this, arguments);

}

Cat.prototype = new Animal;

Cat.prototype.species = 'Cat';

Cat.prototype.talk = function(){ alert('Мяу!'); }

function Dog(name){

Animal.apply(this, arguments);

}

Dog.prototype = new Animal;

Dog.prototype.talk = function(){ alert('Гав!'); }

var sam = new Cat('Sam');

var joe = new Dog('Joe');

sam.sleep(); // Sam спит : Хрррр

joe.sleep(); // Joe спит: Хрррр

alert(sam.species); // Cat

alert(joe.species); // Animal – для Dog функция species не определена

Можно продолжить это дальше и создать отдельные функции для различных пород собак или кошек и т.д.

Замыкание (сlosure) является одним из наиболее мощных средств JavaScript. Если воспользоваться простым объяснением, то замыкание связывает внутренние и внешние переменные в функции. Почему это так важно? Потому что замыкание позволяет эмулировать почти любое свойство любого языка программирования, даже если оно не существует в JavaScript. Это звучит немного непонятно, поэтому лучше начать с более простого примера:

function beginAdding(a){

a *= 5;

return function finishAdding(b){ alert(a+b); }

}

var add = beginAdding(10);

add(20); // 70

Можно видеть, что в приведенном коде переменной 'a' присваивается значение 10 и передается в функцию beginAdding, в то время как переменной 'b' присваивается значение 20 и передается в функцию finishAdding.

А что содержится в переменной 'add'? Она содержит функцию finishAdding с копией связанной с ней всей функции beginAdding. Копия переменной 'a' из beginAdding сохраняется в памяти для дальнейшего использования.

Теперь, имея представление о замыкании, прежде чем продолжать, необходимо обсудить проблему утечки памяти. Internet Explorer, в частности, подвержен достаточно неприятным утечкам

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату