Created
May 31, 2013 19:02
-
-
Save zandroid/5687166 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Rect(colot, width, height) { | |
// задаём поля, в будущем можем их изменить напрямую | |
this.color = color; | |
this.width = width; | |
this.height = height; | |
} | |
// [1.1] расширяем прототип: | |
// то же самое получим вызовом jQuery.extend(Rect.prototype, { ... }); | |
Rect.prototype.s = function() { | |
// площадь | |
return this.width * this.height; | |
}; | |
Rect.prototype.p = function() { | |
// периметр | |
return 2 * (this.width + this.height); | |
}; | |
// [1.2] можно и так задать прототип, если класс не наследуеся от другого, так меньше писанины | |
// - почему нельзя, если наследуется? (= убьём наследование, объяснение ниже) | |
Rect.prototype = { | |
// т.к. создаём новый объект типа Object, то и конструктор у него будет Object | |
// поэтому требуется явно указать конструктор (вдруг он нам где-нибудь понадобится, например см. ниже) | |
constructor: Rect, | |
s: function() { | |
return this.width * this.height; | |
}, | |
p: function() { | |
return 2 * (this.width + this.height); | |
} | |
}; | |
function Square(color, width) { | |
// вызов базового конструктора | |
Rect.call(this, color, width, width); // or Rect.apply(this, [ color, width, width ]); | |
} | |
/* наследование: | |
Вообще парадигма прототипов сводится к тому, что у инстанса класса | |
есть скрытое* свойство __proto__ указывающее на Constructor.prototype, | |
и если какое-то поле или метод не найдены у инстанса, то происходит поиск | |
в прототипе, прототипе прототипа и т.д. | |
А наследование Squre от Rect в этом контексте означает, что | |
Square.__proto__.__proto__ => (Square.prototype.__proto__ =>) Rect.prototype, | |
т.е. прототип для Square должен быть "инстансом" Rect | |
*/ | |
// [2.0] Просто скопировать все методы из протитпа базового класса в прототип наследника | |
// Не является наследованием, т.к. изменение потом прототипа базового класса никак не повлияет | |
// на класс наследика и не будет работать оператор instanceof ( sq instanceof Rect => false ) | |
jQuery.extend(Square.prototype, Rect.prototype); | |
// [2.1] Плохой способ, т.к. отрабатывает конструктор базового класса | |
// и в прототип попадают поля, относящиеся к инстансу, но вполне годный, если писать | |
// конструктор базового класса определённым образом | |
// - каким образом надо написать конструктор базового класса Rect? (= если нет параметров, то сразу return) | |
Square.prototype = new Rect(); | |
Square.prototype.constructor = Square; // вернули конструктор | |
// а дальше расширять прототип можно только с помощью явных присвоений или jQuery.extend, см. [1.1] | |
// [2.2] Хитрый способ, всякий уважающий себя JS-программер должен его знать, понимать и использовать | |
function F(){}; // создали пустой конструктор | |
F.prototype = Rect.prototype; // присвоили тот же самый прототип (по сути, просто заменили конструктор на пустой) | |
Square.prototype = new F(); // получили что и требовалось: Square.prototype.__proto__ => Rect.prototype | |
Square.prototype.constructor = Square; // вернули ссылку на родной конструктор | |
// [2.3] Новомодный способ (ECMAScript5), поддерживается IE9+, FF4+ | |
Square.prototype = Object.create(Rect.prototype); // получили: Square.prototype.__proto__ => Rect.prototype | |
Square.prototype.constructor = Square; // вернули ссылку на родной конструктор | |
// - Зачем же мы везде возвращали ссылку на родной конструктор? | |
// = у инстанса можно определить локальное поле/метод, которое перекроет поле из конструктора, | |
// но к прототипу можно обратиться по имени функции конструктора или как раз через свойство .constructor | |
// и для этого не требуется иметь доступ к функции-конструктору | |
square1.s = function() { | |
console.log('trace calling of the square1 method "s"'); | |
return this.constructor.prototype.s.apply(this, arguments); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment