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();
};
var ParentClass = (function () {
// Constructor
function ParentClass(message) {
// Constructor body
this.greeting = message;
this.x = 1;
this.y = 2;
this.z = 3;
}
// Public function
ParentClass.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return ParentClass;
})();
var ChildClass = (function (parentClass) {
// Extend
extend(ChildClass, parentClass);
// Constructor
function ChildClass(message) {
parentClass.apply(this, arguments); // или можно сделать частично parentClass.call(this, message);
this.greeting = message;
}
// Public variable
ChildClass.prototype.name = 'Parent';
// Public function
ChildClass.prototype.greet = function () {
return 'Hello, ' + this.greeting;
};
// Public function
ChildClass.prototype.hey = function () {
return 'Hey! ' + privateFunc();
};
// Private variable
var privateVar = 'Hello';
// Private function
function privateFunc () {
return privateVar + ' my friend!';
}
// Static variable
ChildClass.staticVar = 'I am static variable';
// Static function
function staticFunc () {
return 'I am static function';
}
return ChildClass;
})(ParentClass);
var SubClass = (function (parentClass) {
extend(SubClass, parentClass);
function SubClass(message) {
parentClass.apply(this, arguments);
this.greeting = message;
}
SubClass.prototype.greet = function () {
return 'Hello, ' + this.greeting;
};
SubClass.prototype.hey = function () {
return 'Hey!';
};
return SubClass;
})(ChildClass);
var parentObject = new ParentClass('world');
var childObject = new ChildClass();
var subObject = new SubClass();
console.log(parentObject.greet());
console.log(childObject.hey());
console.log(subObject.hey());
Примеси - Mixins
function applyMixins(derivedCtor, baseCtors) {
baseCtors.forEach(function (baseCtor) {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(function (name) {
derivedCtor.prototype[name] = baseCtor.prototype[name];
});
});
}
// Disposable Mixin
var Disposable = (function () {
function Disposable() {
}
Disposable.prototype.dispose = function () {
this.isDisposed = true;
};
return Disposable;
})();
// Activatable Mixin
var Activatable = (function () {
function Activatable() {
}
Activatable.prototype.activate = function () {
this.isActive = true;
};
Activatable.prototype.deactivate = function () {
this.isActive = false;
};
return Activatable;
})();
var SmartObject = (function () {
function SmartObject() {
var _this = this;
// Disposable
this.isDisposed = false;
// Activatable
this.isActive = false;
setInterval(function () {
return console.log(_this.isActive + " : " + _this.isDisposed);
}, 500);
}
SmartObject.prototype.interact = function () {
this.activate();
};
return SmartObject;
})();
applyMixins(SmartObject, [Disposable, Activatable]);
var smartObj = new SmartObject();
setTimeout(function () {
return smartObj.interact();
}, 1000);
Пример работы со статичными переменными и функциями внутри класса.
var Point = (function () {
// Object constructor
function Point(x, y) {
this.x = x;
this.y = y;
}
// Public function
Point.prototype.distance = function (p) {
var dx = this.x - p.x;
var dy = this.y - p.y;
return Math.sqrt(dx * dx + dy * dy);
};
// Static function
Point.distance = function (p1, p2) {
return p1.distance(p2);
};
// Static variable
Point.origin = new Point(0, 0);
return Point;
})();
Пример вызова родительского класса в дочернем классе.
var Point = (function () {
// Constructor
function Point(x, y) {
this.x = x;
this.y = y;
}
// Public function
Point.prototype.toString = function () {
return 'x=' + this.x + ' y=' + this.y;
};
return Point;
})();
var ColoredPoint = (function (parentClass) {
// Extend parent class
extend(ColoredPoint, parentClass);
// Constructor
function ColoredPoint(x, y, color) {
parentClass.apply(this, arguments);
parentClass.call(this, x, y);
this.color = color;
}
// Public function
ColoredPoint.prototype.toString = function () {
return parentClass.prototype.toString.call(this) + ' color=' + this.color;
};
return ColoredPoint;
})(Point);
Пример наследования класса во множестве дочерних классов.
var Control = (function () {
function Control() {}
return Control;
})();
var Button = (function (parentClass) {
extend(Button, parentClass);
function Button() {
parentClass.apply(this, arguments);
}
Button.prototype.select = function () {};
return Button;
})(Control);
var TextBox = (function (parentClass) {
extend(TextBox, parentClass);
function TextBox() {
parentClass.apply(this, arguments);
}
TextBox.prototype.select = function () {};
return TextBox;
})(Control);
var Image = (function (parentClass) {
extend(Image, parentClass);
function Image() {
parentClass.apply(this, arguments);
}
return Image;
})(Control);
Public, Private, и Privileged переменные и функции.
Public
function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;
Private
function Constructor(...) {
var that = this;
// Private
var membername = value;
function membername(...) {...}
}
Примечание: данное выражение
function membername(...) {...}
это сокращенная запись такого выражения
var membername = function membername(...) {...};
Privileged
function Constructor(...) {
this.membername = function (...) {...};
}
Пример.
function Constructor (param) {
// Public variable
this.member = param;
// Private variables. They are not accessible to the outside, nor are they accessible to the object's own public methods. They are accessible to private functions.
var secret = 3;
var that = this;
// Private function inside constructor. Private methods cannot be called by public methods. It can be used to make this object limited to 3 uses. To make private methods useful, we need to introduce a privileged method.
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
// Privileged function. A privileged method is able to access the private variables and methods, and is itself accessible to the public methods and the outside. It is possible to delete or replace a privileged method, but it is not possible to alter it, or to force it to give up its secrets.
this.service = function () {
return dec() ? that.member : null;
};
}
Пример модуля.
var M;
(function (M) {
var s = "hello";
function f() {
return s;
}
M.f = f;
})(M || (M = {}));
M.f();
Пример экспортирования значений в модуль.
(function (exports) {
var key = generateSecretKey();
function sendMessage(message) {
sendSecureMessage(message, key);
}
exports.sendMessage = sendMessage;
})(MessageModule);
Загрузка модулей осуществляется в стиле Require JS.
define(["require", "exports", "log"], function(require, exports, log) {
log.message("hello");
});
Пояснения.
Наследование свойств, определенный в конструкторе класса через this.
var Parent = function(){
this.surname = 'Brown';
};
var Child = function(){
Parent.apply(this, arguments);
};
var boy = new Child();
console.log(boy.surname); // Brown
Выше написанный код равносилен следующему коду.
Наследование свойств, определенный в prototype класса через prototype.
function inherit (proto) {
function F() {}
F.prototype = proto;
return new F();
}
Parent.prototype.surname = 'Brown';
var Child = function(){};
Child.prototype = inherit(Parent.prototype);
var boy = new Child();
console.log(boy.surname); // Brown
Альтернативная запись функции наследования классов (менее предпочтительная, чем в TypeScript).
function extend(Child, Parent) {
Child.prototype = inherit(Parent.prototype);
Child.prototype.constructor = Child;
Child.parent = Parent.prototype;
}
function inherit(proto) {
function F() {}
F.prototype = proto;
return new F();
}
Наследование свойств, определенный в конструкторе класса через this.
var Parent = function(){
this.surname = 'Brown';
};
var Child = function(){
Parent.apply(this, arguments);
};
var boy = new Child();
console.log(boy.surname); // Brown
Выше написанный код равносилен следующему коду.
Наследование свойств, определенный в prototype класса через prototype.
function inherit (proto) {
function F() {}
F.prototype = proto;
return new F();
}
Parent.prototype.surname = 'Brown';
var Child = function(){};
Child.prototype = inherit(Parent.prototype);
var boy = new Child();
console.log(boy.surname); // Brown
Альтернативная запись функции наследования классов (менее предпочтительная, чем в TypeScript).
function extend(Child, Parent) {
Child.prototype = inherit(Parent.prototype);
Child.prototype.constructor = Child;
Child.parent = Parent.prototype;
}
function inherit(proto) {
function F() {}
F.prototype = proto;
return new F();
}
Комментариев нет:
Отправить комментарий