Форум программистов, компьютерный форум, киберфорум
JavaScript
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
9944 / 2945 / 496
Регистрация: 05.10.2013
Сообщений: 7,998
Записей в блоге: 240

ООП ES5 Code review. Может у кого-нибудь будут замечания к коду.

09.03.2018, 11:46. Показов 1670. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Я тоже изучаю ООП на JavaScript, но для браузеров, которые не поддерживают ES6. Хочу научиться использовать классическое ООП на классическом JS, в который переводит babel из ES6.

Я написал небольшой пример. ЛКМ добавляет объект. ПКМ удаляет указанные курсором объекты: демка в песочнице



В этом примере классы классы Square, Trinagle и Circle наследуются от базового класса Shape. Базовый класс Shape содержит свойства, которые используются в классах наследниках. ООП убирает дублирование кода. Базовый класс Shape определяет два метода: Draw и IsCollision, которые должны перезагружаться в классах наследниках. Эти классы переопределяют метод Draw и IsCollision. Я вынес общий код из переопределённого метода Draw этих классов в метод Draw класса Shape. А в данных классах в их методе Draw вызываю метод Draw базового класса.

JavaScript
1
2
3
Shape.prototype.Draw = function() {
    this._ctx.fillStyle = this._color;
};
JavaScript
1
2
3
4
Circle.prototype.Draw = function () {
    Shape.prototype.Draw.call(this);
    /* ... */
}
В примере используется паттерн синглтон для объекта-синглтона Scene. Потому что в программе только одна сцена.

Может у кого-нибудь будут замечания к коду, как можно сделать ещё более организацию кода, для упрощения его понимания, то есть управление сложностью за счёт ООП.

index.html
PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html>
 
<head>
    <title>Canvas API. Drawing shapes. OOP</title>
    <script src="Shape.js"></script>
    <script src="Square.js"></script>
    <script src="Triangle.js"></script>
    <script src="Circle.js"></script>
    <script src="Scene.js"></script>
    <script src="main.js"></script>
    <style>
        #renderCanvas {
            border: solid 1px;
        }
    </style>
</head>
 
<body>
    <div>
        <input id="radioSquare" type="radio" name="shape" value="Square" checked><label>Square</label><br>
        <input id="radioTriangle" type="radio" name="shape" value="Triangle"><label>Triangle</label><br>
        <input id="radioCircle" type="radio" name="shape" value="Circle"><label>Circle</label><br>
    </div>
    <canvas id="renderCanvas" width="400" height="400"></canvas>
</body>
 
</html>
main.js
JavaScript
1
2
3
4
5
6
"use strict";
 
function main() {
    Scene.Initialize("renderCanvas");
}
window.onload = main;
Scene.js
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"use strict";
 
var Scene = (function() {
    var _canvas = null;
    var _ctx = null;
    var _backgroundColor = "white";
    var _radioSquare = null;
    var _radioTriangle = null;
    var _radioCircle = null;
 
    var _eShapeType = Object.freeze({
        eSquare: 0,
        eTriangle: 1,
        eCircle: 2
    });
    var _currentShape = _eShapeType.eSquare;
 
    var shapeArray = [];
 
    function Initialize(canvasID) {
        _canvas = document.getElementById(canvasID);
        _ctx = _canvas.getContext("2d");
 
        _radioSquare = document.getElementById("radioSquare");
        _radioTriangle = document.getElementById("radioTriangle");
        _radioCircle = document.getElementById("radioCircle");
        _radioSquare.onclick = function() {
            _currentShape = _eShapeType.eSquare;
        }
        _radioTriangle.onclick = function() {
            _currentShape = _eShapeType.eTriangle;
        }
        _radioCircle.onclick = function() {
            _currentShape = _eShapeType.eCircle;
        }
 
        var x, y, r, g, b, size;
        for (var i = 0; i < 2; i++) {
            x = _GetRandomInt(100, 300);
            y = _GetRandomInt(100, 300);
            r = _GetRandomInt(0, 255);
            g = _GetRandomInt(0, 255);
            b = _GetRandomInt(0, 255);
            size = _GetRandomInt(40, 80);
            var square = new Square(_ctx, x, y, size, 'rgba(' + r + ', ' + g + ', ' + b + ', 255)');
            shapeArray.push(square);
 
            x = _GetRandomInt(100, 300);
            y = _GetRandomInt(100, 300);
            r = _GetRandomInt(0, 255);
            g = _GetRandomInt(0, 255);
            b = _GetRandomInt(0, 255);
            size = _GetRandomInt(40, 80);
            var triangle = new Triangle(_ctx, x, y, size, 'rgba(' + r + ', ' + g + ', ' + b + ', 255)');
            shapeArray.push(triangle);
 
            x = _GetRandomInt(100, 300);
            y = _GetRandomInt(100, 300);
            r = _GetRandomInt(0, 255);
            g = _GetRandomInt(0, 255);
            b = _GetRandomInt(0, 255);
            size = _GetRandomInt(40, 80);
            var circle = new Circle(_ctx, x, y, size, 'rgba(' + r + ', ' + g + ', ' + b + ', 255)');
            shapeArray.push(circle);
        }
 
        // Handler for left and right mouse button click
        _canvas.onmousedown = function(evt) {
            var x = evt.clientX;
            var y = evt.clientY;
            var rect = evt.target.getBoundingClientRect();
            x = Math.floor(x - rect.left);
            y = Math.floor(y - rect.top);
 
            if (evt.button === 0) {
                _AddShape(x, y);
            } else if (evt.button === 2) {
                _DeleteShape(x, y);
            }
        };
 
        // Hide context menu by right mouse click
        window.oncontextmenu = function() {
            return false;
        };
 
        _Draw();
    }
 
    function _AddShape(x, y) {
        var r = _GetRandomInt(0, 255);
        var g = _GetRandomInt(0, 255);
        var b = _GetRandomInt(0, 255);
        var size = _GetRandomInt(40, 80);
        var shape;
        if (_currentShape === _eShapeType.eSquare) {
            shape = new Square(_ctx, x, y, size, 'rgba(' + r + ', ' + g + ', ' + b + ', 255)');
        } else if (_currentShape === _eShapeType.eTriangle) {
            shape = new Triangle(_ctx, x, y, size, 'rgba(' + r + ', ' + g + ', ' + b + ', 255)');
        } else if (_currentShape === _eShapeType.eCircle) {
            shape = new Circle(_ctx, x, y, size, 'rgba(' + r + ', ' + g + ', ' + b + ', 255)');
        }
 
        shapeArray.push(shape);
        _Draw();
    }
 
    function _DeleteShape(x, y) {
        for (var i = 0; i < shapeArray.length; i++) {
            if (shapeArray[i].IsCollision(x, y)) {
                shapeArray.splice(i, 1);
                i = -1;
            }
        }
        _Draw();
    }
 
    /**
     * Returns a random integer between min and max
     * Using Math.round() will give you a non-uniform distribution!
     */
    function _GetRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
 
    function _Draw() {
        _ctx.fillStyle = _backgroundColor;
        _ctx.fillRect(0, 0, _canvas.width, _canvas.height);
 
        for (var i = 0; i < shapeArray.length; i++) {
            shapeArray[i].Draw();
        }
    }
 
    return {
        Initialize: Initialize
    };
}());
Shape.js
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"use strict";
 
function Shape(ctx, x, y, size, color) {
    this._ctx = ctx;
    this._x = x;
    this._y = y;
    this._size = size;
    this._color = color;
}
 
Shape.prototype.Draw = function() {
    this._ctx.fillStyle = this._color;
};
 
Shape.prototype.IsCollision = function(x, y) {
 
};
 
function inheritPrototype(subClass, superClass) {
    var prototype = Object.create(superClass.prototype);
    prototype.constructor = subClass;
    subClass = prototype;
}
Circle.js
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
"use strict";
 
function Circle(ctx, x, y, size, color) {
    Shape.call(this, ctx, x, y, size, color);
}
inheritPrototype(Circle, Shape);
 
Circle.prototype.Draw = function () {
    Shape.prototype.Draw.call(this);
 
    this._ctx.beginPath();
    this._ctx.arc(this._x, this._y, this._size, 0, 2 * Math.PI, false);
    this._ctx.closePath();
    
    this._ctx.fill();
}
 
Circle.prototype.IsCollision = function (x, y) {
    var dx = Math.abs(x - this._x);
    var dy = Math.abs(y - this._y);
    return Math.sqrt(dx * dx + dy * dy) < this._size;
}
Square.js
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"use strict";
 
function Square(ctx, x, y, size, color) {
    Shape.call(this, ctx, x, y, size, color);
}
inheritPrototype(Square, Shape);
 
Square.prototype.Draw = function() {
    Shape.prototype.Draw.call(this);
    this._ctx.fillRect(this._x - this._size / 2, this._y - this._size / 2, this._size, this._size);
}
 
Square.prototype.IsCollision = function(x, y) {
    return (this._x - this._size / 2 <= x && x <= this._x + this._size / 2 &&
        this._y - this._size / 2 <= y && y <= this._y + this._size / 2);
};
Triangle.js
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
"use strict";
 
function Triangle(ctx, x, y, size, color) {
    Shape.call(this, ctx, x, y, size, color);
}
inheritPrototype(Triangle, Shape);
 
Triangle.prototype.Draw = function() {
    Shape.prototype.Draw.call(this);
 
    this._ctx.beginPath();
    this._ctx.moveTo(this._x, this._y - this._size);
    this._ctx.lineTo(this._x - this._size, this._y + this._size);
    this._ctx.lineTo(this._x + this._size, this._y + this._size);
    this._ctx.closePath();
 
    this._ctx.fill();
};
 
Triangle.prototype.IsCollision = function(x, y) {
    var Px = x;
    var Py = y;
    var Ax = this._x;
    var Ay = this._y - this._size;
    var Bx = this._x - this._size;
    var By = this._y + this._size;
    var Cx = this._x + this._size;
    var Cy = this._y + this._size;
    //debugger;
    var N1 = (By - Ay) * (Px - Ax) - (Bx - Ax) * (Py - Ay);
    var N2 = (Cy - By) * (Px - Bx) - (Cx - Bx) * (Py - By);
    var N3 = (Ay - Cy) * (Px - Cx) - (Ax - Cx) * (Py - Cy);
    var result = ((N1 > 0) && (N2 > 0) && (N3 > 0)) || ((N1 < 0) && (N2 < 0) && (N3 < 0));
    return result;
};
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.03.2018, 11:46
Ответы с готовыми решениями:

[Code review] ООП ошибки
Здравствуйте! Есть программа и она рабочая. И мне для дальнейшего программирования необходимо знать насколько она правильно, оптимально и...

Может у кого-нибудь есть?
Может у кого-нибудь исходник поисковика, который на основе другого,например яндекся, осуществляет тематический поиск?

Может будут у кого умные мысли по этому поводу...?
Задача следущая: есть табличка статистики. в ней есть поле типа действия, даты и времени, когда данное действие было совершено..Как...

4
9944 / 2945 / 496
Регистрация: 05.10.2013
Сообщений: 7,998
Записей в блоге: 240
12.03.2018, 09:20  [ТС]
На этот вопрос меня вдохновили две темы:
0
Модератор
Эксперт JS
 Аватар для Eva Rosalene
5241 / 2115 / 416
Регистрация: 06.01.2013
Сообщений: 4,846
12.03.2018, 16:44
Цитата Сообщение от 8Observer8 Посмотреть сообщение
но для браузеров, которые не поддерживают ES6
Babel.
Единственное (кажется ), что он не транспайлит - Proxy, но это хоть и мощный, но редко требующийся инструмент.
0
9944 / 2945 / 496
Регистрация: 05.10.2013
Сообщений: 7,998
Записей в блоге: 240
12.03.2018, 17:09  [ТС]
Цитата Сообщение от FraidZZ Посмотреть сообщение
Babel.
Про Babel я знаю, а так же знаю про TypeScript, компилятор которого тоже транслирует в ES5. Я специально в начале оговорился, что хочу без Babel, а именно ООП на ES5. И здесь уточню, что без компилятора TypeScript.

Нашёл в ES5 аналог enum из C++ и C#:
JavaScript
1
2
3
var eTankDirection = Object.freeze({
    eUp: 0, eLeft: 1, eDown: 2, eRight: 3
});
0
90 / 90 / 48
Регистрация: 07.12.2011
Сообщений: 215
14.03.2018, 09:47
Ну тут пример такой очень простой для понимания. Вроде всё хорошо вообщем.

Ну от себя еще:
- x, y и r,g,b: явно виделяются как групы. Их можно в отдельные структуры.
(кусочек который дублируется -воть: 'rgba(' + r + ', ' + g + ', ' + b + ', 255)')

- с класса Scene можно убрать ответственность за создание объектов, а перенести ее в классы - (абстрактные?) фабрики, например.
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.03.2018, 09:47
Помогаю со студенческими работами здесь

может у кого нибудь была такая проблема
вообще такое.купил вчера ноут и взял отсоеденил провод интернета от стационарного компа и подключил в ноут.настроил там интернет. и фишка в...

Есть ли у кого нибудь обработка по загрузке из эксель в приходный документ,где поиск происходил бы по штрих-коду?
УТ 10.3 1С 8.1

Народ посоветуйте где можно скачать или может у кого нибудь завалялось
Всем привет... в общем ситуация одна из самых простых. Ищу вот такой скрипт. Стартовая страница поле запроса, чел вводит скрипт...

Кто-нибудь может начертить блок-схему по коду!!!
Кто-нибудь может начертить блок-схему по коду!!! #include &lt;stdio.h&gt; #include &lt;math.h&gt; int main (void) { long n; double dbln; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru