Как граматно создать конструктор
НЕ ПУГАЙТЕСЬ ЧТО МНОГО ТЕКСТА, ТУТ ВСЕ ПРОСТО!!!
Решил попытаться переписать свой код, и столкнулся с огромным провалом в понимании ООП в javascript, связи с чем прошу вашей помощи в создании эдакого мануала. Я работаю с элементам canvas, но думаю что логика подхода применительно к обычному диву будет такой же. Но не суть, ближе к делу. Пусть у нас будут даны несколько элементов canvas: ... <canvas id="canvasA"></canvas> <canvas id="canvasB"></canvas> <canvas id="canvasC"></canvas> ... и располагаем мы таким набором говнокода (написанным применительно для одного canvas):
function init() { //функция инициализации canvas
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
}
...
function animate() { //функция запускающая отрисовку
requestAnimationFrame(animate);
draw();
}
//координаты мыши относительно элемента канвас
var xMouse=0
var yMouse=0
var HOLD=false
var WIDTH = canvas.offsetWidth
var HEIGHT = canvas.offsetHeight
function draw(){ //отрисовка
ctx.beginPath();
ctx.rect(0, 0, WIDTH , HEIGHT ); // очистка экрана
ctx.fill();
ctx.stroke();
if (HOLD==false)
ctx.strokeText(xMouse + " " + yMouse, 10, 10) // 10 10 -точка вывода координат мыши.
if (HOLD==true)
ctx.strokeText("Click is true", 10, 10)
}
//обработчики:
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
canvas.onmousemove = myMove;
function myUp(e) { HOLD = false }
function myDown(e) { HOLD = true}
function myMove(e) {
xMouse = e.pageX - canvas.offsetLeft
yMouse = e.pageY - canvas.offsetTop
}
Итак, это пожалуй все что нам понадобиться. Задача: отображать на каждом canvas координаты xMouse, yMouse (координаты мышки относительно этого канваса, а не всей страницы), а в случае клика выводить надпись (как видите в случае клика меняется значение переменной HOLD, а в функции отрисовки есть проверка этой переменной) Сложность: Все что я написал действительно является ничем иным как говнокодом, который можно применить к одному единственному элементу canvas, я же хочу сделать универсальный конструктор, но не знаю как, и в этом прошу вашей помощи. Думаю этот урок может быть полезен и другим новичкам js в будущем! |
Все самое важное я написал вам в вашем прошлом посте.
Пример создания конструктора там тоже есть, могу кинуть второй:
var SomeConstructor = function(name) {
this.name = name;
};
SomeConstructor.prototype.getName = function () {
return this.name;
};
var vasia = new SomeConstructor("Вася");
var petia = new SomeConstructor("Петя");
alert([vasia.getName(), petia.getName()]);
Пишите что и где конкретно не получается - вам помогут. За вас нет желания переписывать. |
tsigel,
function SomeConstructor() {}
потому, что может пригодиться function.name (имя класса) |
nerv_,
Ну не знаю. Однажды я брал так имя класса, когда делал одному из базовых классов метод который выдает всю цепочку наследования. Других использований имени класса не было нужно ни разу. К тому же я пишу на TypeScript (в больших проектах сильно помогают интерфейсы), там в генерируемых им классах имен в функции-конструкторе нет. |
Кстати про TypeScript, я заметил что если писать обычный js код, то idea и webshtorm понимают интерфейсы написанные на TypeScript. Так что теоретически можно оттуда тока интерфейсы брать :)
|
На примере Васи и Пети - все предельно понятно, даже про прототипы уже прочитал и тоже вообщем-то понял. В данном случае мы переопределили объект SomeConctructor, добавив в него метод возвращающий имя. К конкретному коду никаких вопросов нет.
Но не понимаю как это применить к моему случаю. у меня сейчас можно сказать что существует уже 1 палитра с кучей переменных и функций их обработки, а хочу я чтобы для каждого canvas своя палитра создавалась, со своими переменными и функциями. т.е. относительно вашего примера, нужно его усложнить так: задан объект вася:
var vasia = {
name: "Vasia O_O",
age: 30,
friends: vasiaFriends
}
var vasiaFriends = ["Egor","Igor","SexyBitch"]
function addAge(){
vasia.age++
}
function addFriends(name){
vasiaFriends.push(name)
}
как теперь мне создать 2 васи и добавить одному из них нового друга, а другому увеличить возраст? |
Цитата:
var SomeConstructor = function(name) {
this.name = name;
this.getName=function(){
return this.name;
};
};
? |
Цитата:
function Person(options) {
this.name = options.name;
this.age = options.age;
this.friends = options.friends;
}
Person.prototype.addAge = function() { this.age++ }
Person.prototype.addFriends = function(name) { this.friends.push(name) }
var vasia1 = new Person({
name: "Vasia 1",
age: 30,
friends: ["Egor","Igor","SexyBitch"]
});
var vasia2 = new Person({
name: "Vasia 2",
age: 30,
friends: ["Egor","Igor","SexyBitch"]
});
vasia1.addFriends('New friend');
vasia2.addAge();
alert( JSON.stringify(vasia1,'',2) );
alert( JSON.stringify(vasia2,'',2) );
|
var SomeConstructor = function(name, age, friends) {
this.name = name;
this.age = age;
this.friends = friends;
};
SomeConstructor.prototype.getName = function () {
return this.name;
};
SomeConstructor.prototype.addAge = function () {
return this.age++;
};
SomeConstructor.prototype.addFriends = function (friend) {
return this.friends.push(friend);
};
var some1 = new SomeConstructor("a", 30, []);
var some2 = new SomeConstructor("b", 30, []);
some1.addAge();
some2.addFriends("gosha");
alert(JSON.stringify(some1,'',2));
alert(JSON.stringify(some2,'',2))
Эх, долго писал :( |
Цитата:
|
kostyanet,
Разница в экономии памяти. У вас функция будет создана для каждого экземпляра, уу меня у каждого экземпляра будет ссылка на функцию из прототипа. Эх, долго писал :( |
Цитата:
vasya.getName(); // vasya но лично мне эта хрень с this'ами не нравится. Это голимые публичные проперти. Смысла в getName() ровно 0, ибо vasya.name дает то же самое. Ну, понятно что в методе может быть что-то посложнее, но все равно нормальный класс должен иметь внутренности и интерфейс. |
tsigel,
Ясно, спасибо. |
Цитата:
|
Цитата:
a=1 Смысла в пременной a нет, ибо 1 дает то же самое |
Цитата:
|
Теперь такой вопрос, я тоже нуждаюсь. Цитата:
SomeConstructor.prototype.getName = function () {
return this.name;
};
SomeConstructor.prototype.addAge = function () {
return this.age++;
};
SomeConstructor.prototype.addFriends = function (friend) {
return this.friends.push(friend);
};
конец цитаты. Это все можно собрать в один прототип который типа класс, и, затем от него все эти методы наследовать через какой-то шланг в конкретном объекте? |
Цитата:
Или ты хочешь суперкласс создать? |
Цитата:
|
kostyanet,
Да
var SomeConstructor = function(name, age) {
this.name = name;
this.age = age;
};
SomeConstructor.prototype.getName = function () {
return this.name;
};
SomeConstructor.prototype.addAge = function () {
return this.age++;
};
var SomeChild = function () {
SomeConstructor.apply(this,arguments)
};
SomeChild.prototype = Object.create(SomeConstructor.prototype);
SomeChild.constructor = SomeChild;
SomeChild.prototype.childMethod = function () {
return true;
}
var child = new SomeChild("child", 20);
alert(JSON.stringify(child, "", 4));
alert(child.childMethod());
|
крутой, вы в прошлой моей теме все засрали, я бы хотел вас попросить не вмешиваться, а то я вас могу травмировать, у меня еще с юзенета могучий опыт имеется.
Там я задавал именно такой вопрос, про эту самую память. Не скажу что она меня сильно волнует, ибо и без скриптов FF хавает изрядно, подумаешь еще пару мегов, а Chrome вообще может полтора гига засосать своим leakage. Но тем не менее, вот усеченный код, структура вся сохранена
var FormField=function(elem){
var type= elem.type,
def= elem.value,
rules={};
return {
validate:function() {
value=elem.value.trim();
if(type in rules)
rules[type]();
else
rules.text();
}
};
};
// load
var some[]=FormField[elem];
Я понимаю у каждого будет своя копия (инстансь) объекта который возвращает функция, а все ее кишки тоже скопируются? |
Цитата:
Например так:
var Class = (function () {
var private
var Class = function () {}
Class.prototype.someMethod = function() {
private ...
};
...
return Class;
})();
|
Цитата:
|
Цитата:
|
kostyanet,
Да ты долбоеб, по ходу, совсем мягкий, блять. Нахуй ты мне сдался. |
tsigel,
Спасибо еще раз. Но выглядит страшновато. Надо привыкнуть, подольше смотреть, не отворачиваться. :) |
Цитата:
|
Развели тут срач в моей теме... ><
Вообщем, кажется, я наконец-то понял, поправьте меня, если я туплю. 1. Я создаю конструктор, который должен проинициализировать все мои переменные используемые в данном canvas. Т.е. допустим я использую: ...
var x0Multi
var y0Multi
var x1Multi
var y1Multi
var xMouse
var yMouse
var TEMP = ""
var ActionState = "single"
var Creating = "none"
var InFocus = { H: [], S: [], CvC: [] }
var DATA = []
var conn = []
var vers = []
var edges = []
var cnEdg = 0
var cnCon = 0
var cnVer = 0
var idV = 0
var idE = 0
... тогда я получу что-то вроде:
var SomeConstructor = function() {
this.x0Multi
this.y0Multi
this.x1Multi
this.y1Multi
this.xMouse
this.yMouse
this.TEMP = ""
this.ActionState = "single"
this.Creating = "none"
this.InFocus = { H: [], S: [], CvC: [] }
this.DATA = []
this.conn = []
this.vers = []
this.edges = []
this.cnEdg = 0
this.cnCon = 0
this.cnVer = 0
this.idV = 0
this.idE = 0
};
2. Все функции я должен переписать в ввиде расширения прототипа. Т.е.: было
...
function drawMultiSelect() {
ctx.beginPath();
ctx.rect(x0Multi, y0Multi, x1Multi - x0Multi, y1Multi - y0Multi);
console.log(x0Multi + " " + y0Multi + " " + xMouse + " " + yMouse)
ctx.strokeStyle = "rgba(0,0,255,0.5)";
ctx.fillStyle = "rgba(0,0,255,0.3)";
ctx.fill();
ctx.stroke();
}
...
стало:
SomeConstructor.prototype.drawMultiSelect() {
this.ctx.beginPath();
this.ctx.rect(x0Multi, y0Multi, x1Multi - x0Multi, y1Multi - y0Multi);
this.ctx.strokeStyle = "rgba(0,0,255,0.5)";
this.ctx.fillStyle = "rgba(0,0,255,0.3)";
this.ctx.fill();
this.ctx.stroke();
}
остается мне только одно не понятным. допустим я в конструкторе я определил переменную this.ctx, как потом мне обратиться к ней из функции определенной в прототипе? как к ctx или как к this.ctx? |
Цитата:
Я делал систему логирования, которая в случае ошибки отправляла на сервер ошибку, имя метода и класса (со всей цепочкой наследования) в котором произошла ошибка. |
Цитата:
|
Цитата:
|
Цитата:
|
Не получается, набрался наглости попросить показать как из того что было
var FormField=function(elem){
var type= elem.type,
def= elem.value,
rules={};
return {
validate:function() {
value=elem.value.trim();
if(type in rules)
rules[type]();
else
rules.text();
}
};
};
// load
var some[]=FormField[elem];
сделать правильный объект, который бы содержал только данные, а методы держал бы в прототипе. На php такая задача решается через скажем protected static function(), поскольку статика не создает экземпляров. Ну и там еще легко делаются геттеры с сеттерами всякие. В итоге в объекте может быть ровно 1 array в качестве тех самых данных. |
tsigel, уверен что это правильно будет работать?
var Class = (function () {
var private
var Class = function () {}
Class.prototype.setPrivate = function(value) {
private = value;
};
Class.prototype.getPrivate = function() {
return private;
};
return Class;
})();
var o1 = new Class();
var o2 = new Class();
o1.setPrivate('x');
o2.setPrivate('y');
alert( o1.getPrivate() );
|
Цитата:
|
Цитата:
SomeConstructor.prototype.drawMultiSelect=function(){}
надо по-идее. У Вас что, это работает? |
danik.js,
А для синглтона подойдет XD Я предпочитаю на "_" и доках выезжать. без замут с замыканиями. Если поизвращаться, то наверно можно создать в замыкании массив объектов scope, каждый из которых соответствовал бы конкретному экземпляру. |
Цитата:
|
Цитата:
clos=function(arg){
var proto={get: function(){alert(this.a)}}
var o=Object.create(proto)
o.a=1
return o[arg]()
}
clos("get")
|
Цитата:
|
| Часовой пояс GMT +3, время: 15:38. |