Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
function MyClass() {
....
}
var obj = new MyClass();
function MyFoo() {
MyClass.apply(this, arguments);
....
}
inherits(MyFoo, MyClass);
var foo = new MyFoo();
function MyFoo() {
var self = this;
MyClass.apply(this, arguments);
this.method1 = function () {}
this.method2 = function () {}
}
class MyFoo {
function __construct () {
$self = $this;
$this->method1 = function () use($self) { };
$this->method2 = function () use($self) { };
}
}
function MyFoo() {
}
MyFoo.prototype = {
method1: function () {},
method2: function () {}
};
function MyFoo() {
var self = this;
MyClass.apply(this, arguments);
//Вот это???? это не мое и придумывать того чего нет не надо.
this.method1 = function () {}
this.method2 = function () {}
}
exports.inherits = function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
+function()
{
classes.Some = function(){ return this.init.apply( this, arguments ); }
classes.Some.prototype =
{
init: function( options )
{
},
// public
someMethod: function(){}
}
function someProtectedMethod()
{
}
}();
В дальнейшем схему можно наворотить, например, создать классо-фабрику, которая будет организовывать 2 уровня прототипа и упростит работу с private методами (к примеру, их можно поместить в 1 объект, а затем про-bind-ить на экземпляр «класса»).1. Зачем вам наследование? Можете привести реальный пример?
Я надеюсь ответил на ваш вопросНет. Вопрос тот же — можете привести реальный пример? Всё таки JavaScript имеет своеобразное ООП, и до сих пор у меня не возникало необходимости в частом использовании прототипа дальше первого уровня (и уж тем более необходимости медленных get-ов и set-ов). В исключительной ситуации достаточно сымитировать аналог php-ых traits. Какого уровня js-приложения вы пишете?
{
$acsessor1: 0,
$acsessor2: 0,
set__: function( prop, val ) {
},
get__: function( prop ) {
}
}{
set__acsessor1: function( val ) {
},
get__acsessor1: function() {
},
set__acsessor2: function( val ) {
},
get__acsessor2: function() {
}
}{
$acsessor1: 0,
$acsessor2: 0,
set__: function( prop, val ) {
if (prop == 'accessor1')
{
this.set_accessor1()
}
else if (prop == 'accessor2')
{
this.set_accessor2()
}
},
get__: function( prop ) {
if (prop == 'accessor1')
{
return this.get_accessor1()
}
else if (prop == 'accessor2')
{
return this.get_accessor2()
}
}
}
{
_props :
{
// Универсальные обработчики
"set *" : function(value){},
"get *" : function(value){},
// Обработчики свойства name
"set name" : function(value){},
"get name" : function(value){},
// Ну или более наглядно, но более экзотично
"-> name" : function(value){},
"<- name" : function(){}
}
}
accessors: {
accessor1: function( val, isSet ) {
if ( !isSet ) {
return myValue;
}
myValue = val;
}
accessor2: function( val, isSet ) {
if ( !isSet ) {
return myValue;
}
myValue = val;
}
}
..............
{
$accessor1: 0,
$accessor2: 0,
set__: function( prop, val ) {
accessors[ prop ] && accessors[ prop ].call( this, val, true );
},
get__: function( prop ) {
return accessors[ prop ] && accessors[ prop ].call( this );
}
}classes.Class( "SuperButtonClass extends ButtonClass", {
property : 'foo',
anothProp: 'bar',
$accessors: {
accessor1: {
get: function (currentValue) {
return currentValue + ': getter';
},
set: function (newValue) {
return 'setter: ' + newValue;
}
},
accessor2: {
get: function (currentValue) {
return currentValue + ': second getter';
},
set: function (newValue) {
return 'second setter: ' + newValue;
}
}
},
method: function () {
return Math.random() * 42;
}
});
classes.Class( "ButtonClass", {
$accessors: {
accessor1: {
get: function (currentValue) {
return currentValue + ': getter';
},
set: function (newValue) {
return 'setter: ' + newValue;
}
}
}
});
classes.Class( "SuperButtonClass extends ButtonClass", {
property : 'foo',
anothProp: 'bar',
$accessors: {
accessor1: {
get: function (currentValue) {
return currentValue + ': getter';
},
set: function (newValue) {
return 'setter: ' + newValue;
}
},
accessor2: {
get: function (currentValue) {
return currentValue + ': second getter';
},
set: function (newValue) {
return 'second setter: ' + newValue;
}
}
},
method: function () {
return Math.random() * 42;
}
});{
$accessor1: 0,
$accessor2: 0,
set__: function( prop, val ) {
this.parent.set__( prop, val );
accessors[ prop ] && accessors[ prop ].call( this, val, true );
},
get__: function( prop ) {
if ( accessors[ prop ] ) {
return accessors[ prop ].call( this );
}
return this.parent.get__( prop, val );
}
}classes.Class( "Foo", {
$accessor: 0,
set__: function( prop, val ) {},
get__: function( prop ) {
console.log('Foo.get');
}
});
classes.Class( "Bar extends Foo", {
$accessor: 0,
get__: function( prop ) {
console.log('Bar.get');
return this.parent.get__( prop, val );
}
});
classes.Class( "Qux extends Bar", {
$accessor: 0,
get__: function( prop ) {
console.log('Qux.get');
return this.parent.get__( prop, val );
}
});
backbone.js, то логично было бы поступить так:
{
_props:
{
// Универсальные обработчики
«set *»: function(value){},
«get *»: function(value){},
// Обработчики свойства name
«set name»: function(value){},
«get name»: function(value){},
// Ну или более наглядно, но более экзотично
"-> name": function(value){},
"< — name": function(){}
}
}
{
_props :
{
// Универсальные обработчики-роутеры
"set *" : function(prop, value){},
"get *" : function(prop){},
// Обработчики свойства name
"set name" : function(value){},
"get name" : function(value){},
// Ну или более наглядно, но более экзотично
"-> name" : function(value){},
"<- name" : function(){}
}
}
Class( "Factory", {
// старый вариант, так же работает
$accessor1: 0,
$accessor2: 0,
// сеттеры для универсальных свойств, указанных выше со знаком доллара
__set: function( prop, value ) {
//
},
// гкттер для универсальных свойств, указанных выше со знаком доллара
__get: function( prop ) {
//
},
// сеттер для свойства name
"set name": function( value ) {
},
// геттер для свойства name
"get name": function() {
}
});Class( window, "Factory", {} ); // создали в глобальном контекстеClass.UI.button.create(), в объекте передаваемом в create можно указать что именно копировать из прототипа (например директивой meta), иначе брать всё. Можно еще добавить (ну это уже плюшка) общий (shared) объект, для соединений, конфигов и т.п.Class.UI.button.create() я не совсем понял что вы имеете ввиду. То-есть нужен метод который будет срабатывать до создания объектов, в котором будут указываться правила?// создаем класс UI, дефолтный для всех дочерних элементов интерфейса
// в описании указываем, что у него есть обязательный метод: draw
// и добавляем метод titleFromArray
Class.create('UI', { abstract : ["draw"], titleFromArray : function(arr){ } })
// создаем класс Button, который реализует метод draw и наследует метод titleFromArray от UI
Class.UI.create('button', { parent : ['titleFromArray'], draw : function(){ } })
abstract и parent даны для примера, и лучше их заменить чем-то более далеким от классического ООП, например, strict и inherit соответственно.// Вариант с использованием контекста библиотеки
var button= new Class.UI.button()
// Ну или при создании указать контекст window и обращаться напрямую
var button2= new UI.button()
var q = new Class.UI.button.Lala.Trata.TirTir.Q.W.E.R.T.Y.U.I.P.A.S.D.F.G.H();По моему это немного не красиво, да и еще и не удобно. Хотя возможно вы имеете ввиду что то иное. И я просто вас не понял.var Button= UI.button, либо использовать для этого ваши же контексты.UI.button.dropdown список сохраняет наследственность и описательность, показывая что и где копать, да и в принципе ограничивается 3-уровнями, что приемлемо.При наследовании через прототипы все порожденные экземпляры будут использовать общие приватные переменные родительского класса
;var MyClass = (function() {
var _privateVar1 = 0,
_privateVar2 = 1,
_privateVar3 = 3;
var MyClass = function() {
console.log(_privateVar1, _privateVar2, _privateVar3)
}
MyClass.prototype.getPrivateVar1 = function() {
return _privateVar1
};
MyClass.prototype.setPrivateVar1 = function(value) {
_privateVar1 = value
return this
};
return MyClass
});
В чём профит ваших аксессоров в сравнении с простым обращением к свойствам объекта?
Зачем в геттере/сетере писать километровый switch
...
if ( property === "text" ) {
// то меняем текст кнопки на новое значение
this.node().innerHTML = value;
}
...
..
setText: function(value) {
// то меняем текст кнопки на новое значение
this.node().innerHTML = value;
}
..
Вообще-то, «километровый switch» можно и не писать. Обычно сеттеров (и геттеров) — один-два на объект. Но если больше — можно сделать объект setters, в котором по имени изменяющегося св-ва будут храниться нужные функции. Тогда достаточно будет просто сделать так: setters[propertyName]().
;var MyClass = (function() {
var _properties = {
'a': 1,
'b': 2,
'c': 'test string'
}
var MyClass = function() {}
MyClass.prototype.property = function(name, value) {
if (typeof name === 'undefined') throw "No name specified"
if (_properties.hasOwnProperty(name)) {
if (typeof value === 'undefined') {
return _properties[name]
} else {
_properties[name] = value
return this
}
} else throw "Property with name '" + name + "' not found";
}
return MyClass
}());
var inst = new MyClass()
inst.property('a') // => 1
inst.property('b') // => 2
inst.property('c') // => test string
inst.property('d') // => "Property with name 'd' not found"
inst.property('a', 10)
.property('b', 15)
.property('c', 'new string')
.property('d', 'fail') // => "Property with name 'd' not found"
inst.property('a') // => 10
inst.property('b') // => 15
inst.property('c') // => new string
inst.property('d') // => "Property with name 'd' not found"
inst.property() // => "No name specified"
...
var MyClass = function() {
this.a = 1
this.b = 2
this.c = 'test string'
}
...
Использование классов в JavaScript