<!DOCTYPE html>
<html>
<meta charset="utf-8" />
<head><title>JavaScript Class</title></head>
<body>
<script type="text/javascript">
var extend = this.extend || function (childClass, parentClass) {
// Копируем в дочерний класс статичные свойства и методы из родительского класса
for (var key in parentClass) {
if (parentClass.hasOwnProperty(key)) {
childClass[key] = parentClass[key];
}
}
// Ставим ссылку конструктора на дочерний класс
function F () {
this.constructor = childClass;
}
F.prototype = parentClass.prototype; // Копируем свойства и методы прототипа из родителя во временную функцию
childClass.prototype = new F(); // Присваиваем дочернему прототипу объект, созданный из родительского класса
childClass.__super__ = parentClass.prototype; // Для непосредственного вызова родительских методов, если потребуется, хотя это редко будет нужно (взято из coffeescript). Можно использовать в дочернем методе, вызывая дополнительно метод родительского класса внутри него так ChildClass.__super__.move.call(this, 5);
};
var mixin = this.mixin || function (childClass) {
var mixins = Array.prototype.slice.call(arguments, 1) // Классы с набором методов mixin
, i
, len = mixins.length
, key;
if (len) {
// Для каждого элемента из массива mixins копируем статичные свойства и методы в дочерний класс
for (i = 0; i < len; i++) {
for (key in mixins[i]) {
// Копируем в дочерний класс статичные свойства и методы из примеси
if (mixins[i].hasOwnProperty(key)) {
childClass[key] = mixins[i][key];
}
}
}
// Ставим ссылку конструктора на дочерний класс
function F () {
this.constructor = childClass;
}
F.prototype = childClass.prototype; // Копируем свойства и методы прототипа из примеси во временную функцию
for (i = 0; i < len; i++) {
// Копируем в прототип дочернего класса свойства и методы из прототипа примеси
for (key in mixins[i].prototype) {
F.prototype[key] = mixins[i].prototype[key];
}
}
childClass.prototype = new F(); // Присваиваем дочернему прототипу объект, созданный из примеси
}
};
</script>
<script type="text/javascript">
// Родительский класс
var ParentClass = (function(){
// Constructor
function ParentClass (initVar, initMethod) {
// Init public
this.initVar = initVar;
this.initMethod = initMethod;
// Privilege public
this.privilegeVar = '1) ' + (new Date()).getTime();
this.privilegeMethod = function () {console.log('2) ' + (new Date()).getTime());};
// Private
var privateVar = 1;
function privateFunction () {}
// Events
var self = this;
document.addEventListener(click, funciton(){
alert(self.privilegeVar);
}, false);
// Если конструктор вдруг был вызван без слова new
if (!(this instanceof ParentClass)) {
return new ParentClass(initVar, initMethod);
}
}
ParentClass.prototype.constructor = ParentClass;
// Public
ParentClass.prototype.publicVar = '5) ' + (new Date()).getTime();
ParentClass.prototype.publicMethod = function () {console.log('6) ' + (new Date()).getTime());};
// Private использовать не рекомендуется, так как их изменение в классе потомке влияет на родительский класс
var privateVar = '7) ' + (new Date()).getTime();
function privateMethod () {console.log('8) ' + (new Date()).getTime());}
ParentClass.prototype.getPrivateVar = function () {return privateVar;};
ParentClass.prototype.setPrivateVar = function (value) {privateVar = value;};
ParentClass.prototype.getPrivateMethod = function () {return privateMethod;};
// Static
ParentClass.staticVar = '9) ' + (new Date()).getTime();
ParentClass.staticMethod = function () {console.log('10) ' + (new Date()).getTime());};
return ParentClass;
})();
// Примесь
var Mixin = (function(){
function Mixin () {}
Mixin.prototype.mixinMethod = function () {console.log('11) ' + (new Date()).getTime() + ' | ' + this.privilegeVar);};
Mixin.mixinStaticMethod = function () {console.log('12) ' + (new Date()).getTime());};
return Mixin;
})();
mixin(ParentClass, Mixin);
// Простое наследование родительского класса дочерним
var ChildClass = (function(parentClass){
// Extend
extend(ChildClass, parentClass);
// Constructor
function ChildClass (initVar, initMethod) {
parentClass.apply(this, arguments); // Обязательно для наследования классом потомком родительских свойств и методв из Init и Privilege
// Events
var self = this;
document.addEventListener(click, funciton(){
alert(self.privilegeVar);
}, false);
// Если конструктор вдруг был вызван без слова new
if (!(this instanceof ChildClass )) {
return new ChildClass (initVar, initMethod);
}
}
return ChildClass;
})(ParentClass);
// Наследование родительского класса дочерним с перезаписью свойств и методов
var ChildClass = (function(parentClass){
// Extend
extend(ChildClass, parentClass);
// Constructor
function ChildClass (initVar, initMethod) {
parentClass.apply(this, arguments); // Обязательно для наследования классом потомком родительских свойств и методв из Init и Privilege
// parentClass.call(null, publicMethod); // Вызвать конкретный метод родительского класса, если необходимо
// Override Init
this.initVar = initVar;
this.initMethod = initMethod;
// Override Privilege
this.privilegeVar = 'Child 1) ' + (new Date()).getTime();
this.privilegeMethod = function () {console.log('Child 2) ' + (new Date()).getTime());};
// Events
var self = this;
document.addEventListener(click, funciton(){
alert(self.privilegeVar);
}, false);
// Если конструктор вдруг был вызван без слова new
if (!(this instanceof ChildClass )) {
return new ChildClass (initVar, initMethod);
}
}
// Override Public
ChildClass.prototype.publicVar = 'Child 5) ' + (new Date()).getTime();
ChildClass.prototype.publicMethod = function () {console.log('Child 6) ' + (new Date()).getTime());};
// Override Private использовать не рекомендуется, так как их изменение в классе потомке влияет на родительский класс
var privateVar = 'Child 7) ' + (new Date()).getTime();
function privateMethod () {console.log('Child 8) ' + (new Date()).getTime());}
ChildClass.prototype.getPrivateVar = function () {return privateVar;};
ChildClass.prototype.setPrivateVar = function (value) {privateVar = value;};
ChildClass.prototype.getPrivateMethod = function () {return privateMethod;};
// Override Static
ChildClass.staticVar = 'Child 9) ' + (new Date()).getTime();
ChildClass.staticMethod = function () {console.log('Child 10) ' + (new Date()).getTime());};
return ChildClass;
})(ParentClass);
// Тестирование наследования и примешивания примесей
console.log('====================================');
console.log('Создание объекта из родительского класса');
console.log('====================================');
var parentObject = new ParentClass('3) ' + (new Date()).getTime(), function () {console.log('4) ' + (new Date()).getTime());});
console.log('Parent privilegeVar: ' + parentObject.privilegeVar);
console.log('Parent privilegeMethod: ' + parentObject.privilegeMethod);
console.log('Parent initVar: ' + parentObject.initVar);
console.log('Parent initMethod: ' + parentObject.initMethod);
console.log('Parent publicVar: ' + parentObject.publicVar);
console.log('Parent publicMethod: ' + parentObject.publicMethod);
console.log('Parent privateVar: ' + parentObject.getPrivateVar());
console.log('Parent privateMethod: ' + parentObject.getPrivateMethod());
console.log('Parent staticVar: ' + ParentClass.staticVar);
console.log('Parent staticMethod: ' + ParentClass.staticMethod);
console.log('Parent constructor: ' + parentObject.constructor.name);
console.log('Parent mixinMethod: ' + parentObject.mixinMethod);
console.log('Parent mixinStaticMethod: ' + ParentClass.mixinStaticMethod);
parentObject.mixinMethod();
console.log('====================================');
console.log('Создание объекта из дочернего класса');
console.log('====================================');
var childObject = new ChildClass('3) ' + (new Date()).getTime(), function () {console.log('4) ' + (new Date()).getTime());});
console.log('Child privilegeVar: ' + childObject.privilegeVar);
console.log('Child privilegeMethod: ' + childObject.privilegeMethod);
console.log('Child initVar: ' + childObject.initVar);
console.log('Child initMethod: ' + childObject.initMethod);
console.log('Child publicVar: ' + childObject.publicVar);
console.log('Child publicMethod: ' + childObject.publicMethod);
console.log('Child privateVar: ' + childObject.getPrivateVar());
console.log('Child privateMethod: ' + childObject.getPrivateMethod());
console.log('Child staticVar: ' + ChildClass.staticVar);
console.log('Child staticMethod: ' + ChildClass.staticMethod);
console.log('Child constructor: ' + childObject.constructor.name);
console.log('Child mixinMethod: ' + childObject.mixinMethod);
console.log('Child mixinStaticMethod: ' + ChildClass.mixinStaticMethod);
childObject.mixinMethod();
console.log('====================================');
console.log('Создание значений объекта дочернего класса');
console.log('====================================');
childObject.privilegeVar = 1;
childObject.initVar = 2;
childObject.publicVar = 3;
childObject.setPrivateVar(4);
ChildClass.staticVar = 5;
childObject.mixinMethod = function () {console.log('Child new mixinMethod');};
ChildClass.mixinStaticMethod = function () {console.log('Child new mixinStaticMethod');};
console.log('====================================');
console.log('Проверка значений объекта дочернего класса');
console.log('====================================');
console.log('Child privilegeVar: ' + childObject.privilegeVar);
console.log('Child initVar: ' + childObject.initVar);
console.log('Child publicVar: ' + childObject.publicVar);
console.log('Child privateVar: ' + childObject.getPrivateVar());
console.log('Child staticVar: ' + ChildClass.staticVar);
console.log('Child mixinMethod: ' + childObject.mixinMethod);
console.log('Child mixinStaticMethod: ' + ChildClass.mixinStaticMethod);
console.log('====================================');
console.log('Проверка не изменились ли значения объекта родительского класса');
console.log('====================================');
console.log('Parent privilegeVar: ' + parentObject.privilegeVar);
console.log('Parent initVar: ' + parentObject.initVar);
console.log('Parent publicVar: ' + parentObject.publicVar);
console.log('Parent privateVar: ' + parentObject.getPrivateVar());
console.log('Parent staticVar: ' + ParentClass.staticVar);
console.log('Parent mixinMethod: ' + parentObject.mixinMethod);
console.log('Parent mixinStaticMethod: ' + ParentClass.mixinStaticMethod);
// Синглтон
var ParentClass = (function(){
// Constructor
function ParentClass (initVar, initMethod) {
// Init public
this.initVar = initVar;
this.initMethod = initMethod;
// Privilege public
this.privilegeVar = '1) ' + (new Date()).getTime();
this.privilegeMethod = function () {console.log('2) ' + (new Date()).getTime());};
}
ParentClass.prototype.constructor = ParentClass;
// Public
ParentClass.prototype.publicVar = '5) ' + (new Date()).getTime();
ParentClass.prototype.publicMethod = function () {console.log('6) ' + (new Date()).getTime());};
// Private использовать не рекомендуется, так как их изменение в классе потомке влияет на родительский класс
var privateVar = '7) ' + (new Date()).getTime();
function privateMethod () {console.log('8) ' + (new Date()).getTime());}
ParentClass.prototype.getPrivateVar = function () {return privateVar;};
ParentClass.prototype.setPrivateVar = function (value) {privateVar = value;};
ParentClass.prototype.getPrivateMethod = function () {return privateMethod;};
// Static передаются через синглтон
ParentClass.staticVar = '9) ' + (new Date()).getTime();
ParentClass.staticMethod = function () {console.log('10) ' + (new Date()).getTime());};
// Singleton
var instance;
function SingletonParentClass (initVar, initMethod) {
if (!instance) {
instance = new ParentClass(initVar, initMethod);
}
return instance;
}
SingletonParentClass.prototype = ParentClass.prototype;
for (var key in ParentClass) {
if (ParentClass.hasOwnProperty(key)) {
SingletonParentClass[key] = ParentClass[key];
}
}
return SingletonParentClass;
})();
mixin(ParentClass, Mixin);
var ChildClass = (function(parentClass){
// Extend
extend(ChildClass, parentClass);
// Constructor
function ChildClass (initVar, initMethod) {
parentClass.apply(this, arguments); // Обязательно для наследования классом потомком родительских свойств и методв из Init и Privilege
// Init public
this.initVar = initVar;
this.initMethod = initMethod;
// Privilege public
this.privilegeVar = '1) ' + (new Date()).getTime();
this.privilegeMethod = function () {console.log('2) ' + (new Date()).getTime());};
}
// Singleton
/* Вариант 1 */
/*
var instance;
function SingletonChildClass (initVar, initMethod) {
if (!instance) {
instance = new ChildClass(initVar, initMethod);
}
return instance;
}
*/
// Но лучше даже так, чтобы можно было наследовать от Singleton без проблем с замыканием переменной instance, хранящей внутри себя созданный объект
/* Вариант 2 */
/*
function SingletonChildClass (initVar, initMethod) {
if (!SingletonChildClass.instance) {
SingletonChildClass.instance = new ChildClass(initVar, initMethod);
}
return SingletonChildClass.instance;
}
SingletonChildClass.instance = null;
SingletonChildClass.prototype = ChildClass.prototype;
for (var key in ChildClass) {
if (ChildClass.hasOwnProperty(key)) {
SingletonChildClass[key] = ChildClass[key];
}
}
*/
// return SingletonChildClass;
/* Вариант 3 */
return singleton(ChildClass);
})(ParentClass);
/* Вариант 3 */
function singleton (ParentClass) {
function SingletonClass () {
if (!SingletonClass.instance) {
SingletonClass.instance = ParentClass.apply(this, arguments);
}
return SingletonClass.instance;
}
SingletonClass.instance = null;
SingletonClass.prototype = ParentClass.prototype;
for (var key in ParentClass) {
if (ParentClass.hasOwnProperty(key)) {
SingletonClass[key] = ParentClass[key];
}
}
return SingletonClass;
}
// Тестирование синглтона
console.log('====================================');
console.log('Проверка значений синглтона');
console.log('====================================');
var parentObject = new ParentClass('3) ' + (new Date()).getTime(), function () {console.log('4) ' + (new Date()).getTime());});
var singletonObject = new ParentClass('Singleton) ' + (new Date()).getTime(), function () {console.log('Singleton) ' + (new Date()).getTime());});
console.log('Singleton: ' + (parentObject === singletonObject));
console.log('====================================');
console.log('Проверка значений объекта родительского класса');
console.log('====================================');
console.log('Parent privilegeVar: ' + parentObject.privilegeVar);
console.log('Parent privilegeMethod: ' + parentObject.privilegeMethod);
console.log('Parent initVar: ' + parentObject.initVar);
console.log('Parent initMethod: ' + parentObject.initMethod);
console.log('Parent publicVar: ' + parentObject.publicVar);
console.log('Parent publicMethod: ' + parentObject.publicMethod);
console.log('Parent privateVar: ' + parentObject.getPrivateVar());
console.log('Parent privateMethod: ' + parentObject.getPrivateMethod());
console.log('Parent staticVar: ' + ParentClass.staticVar);
console.log('Parent staticMethod: ' + ParentClass.staticMethod);
console.log('Parent constructor: ' + parentObject.constructor.name);
console.log('====================================');
console.log('Проверка значений объекта синглтона');
console.log('====================================');
console.log('Singleton privilegeVar: ' + singletonObject.privilegeVar);
console.log('Singleton privilegeMethod: ' + singletonObject.privilegeMethod);
console.log('Singleton initVar: ' + singletonObject.initVar);
console.log('Singleton initMethod: ' + singletonObject.initMethod);
console.log('Singleton publicVar: ' + singletonObject.publicVar);
console.log('Singleton publicMethod: ' + singletonObject.publicMethod);
console.log('Singleton privateVar: ' + singletonObject.getPrivateVar());
console.log('Singleton privateMethod: ' + singletonObject.getPrivateMethod());
console.log('Singleton staticVar: ' + ParentClass.staticVar);
console.log('Singleton staticMethod: ' + ParentClass.staticMethod);
console.log('Singleton constructor: ' + singletonObject.constructor.name);
// Класс, позволяющий выполнить рендеринг, вставку на страницу, добавление событий и удаление объекта после его использования
var RenderHTMLClass = (function(){
// Constructor
function RenderHTMLClass () {
this.html; // HTML-код объекта с привязанным к нему событиям
this.render(); // Генерирование HTML-кода объекта с привязыванием к нему событий
}
// Public
RenderHTMLClass.prototype.render = function () {
this.html = document.createElement('h1');
this.html.innerHTML = 'Привет';
this.html.addEventListener('click', this._event, false);
};
// Private
RenderHTMLClass.prototype._event = function () {
alert(1);
};
// Clear - Очистка: удаление HTML-кода объекта из DOM и удаление привязанных к нему событий
RenderHTMLClass.prototype.clearBeforeDeleteReference = function () {
this.html.removeEventListener('click', this._event);
document.body.removeChild(this.html);
}
// Delete - Удаление ссылки на объект JavaScript-кода
RenderHTMLClass.prototype.deleteReference = function (referenceName) {
eval(
referenceName + '= null;' // Устанваливая referenceName равным null мы удаляем ссылку на объект, а после можем удалить и сам объект
+ ' delete ' + referenceName + ';'
);
};
return RenderHTMLClass;
})();
console.log('====================================');
console.log('Проверка значений рендеринга объекта');
console.log('====================================');
var renderHTMLObject = new RenderHTMLClass(); // Создание объекта
document.body.appendChild(renderHTMLObject.html); // Вставка объекта на страницу
console.log(renderHTMLObject.html);
renderHTMLObject.clearBeforeDeleteReference(); // Удаление объекта из кода страницы и очистка, привязанных к нему событий
renderHTMLObject.deleteReference('renderHTMLObject'); // Удаление ссылки на объект из JavaScript
console.log(renderHTMLObject.html);
</script>
</body>
</html>
Комментариев нет:
Отправить комментарий