Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 21.08.2014, 21:04
Новичок на форуме
Отправить личное сообщение для meam Посмотреть профиль Найти все сообщения от meam
 
Регистрация: 26.06.2013
Сообщений: 2

Как улучшить код, ооп
http://jsfiddle.net/ovssubp8/12/
Что тут стоит улучшить? Что сделано не правильно и т.д. Надеюсь на вашу помощь

Последний раз редактировалось meam, 21.08.2014 в 21:53. Причина: обновил код
Ответить с цитированием
  #2 (permalink)  
Старый 21.08.2014, 21:30
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

в одном месте так, в другом сяк
this.elem.on('submit', '.todo-form', $.proxy(this.onFormSubmit, this));
//...
this.list.on('click', '.todo-x', this.onXClick.bind(this));


говорит о незнании того, что ты делаешь
onFormSubmit: function(e) {
if(this.input.val().trim() === '') {
*!*
    return false;
*/!*
}
*!*
    e.preventDefault();
*/!*
}


оригинально
function TaskList(el) {
    var that = this;
    // ...
*!*
    this.list.on('click', '.todo-x', this.onXClick.bind(this));
    this.el.on('click', '.todo-remove', this.onRemoveClick.bind(that))
*/!*
}


и т.д.
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #3 (permalink)  
Старый 21.08.2014, 21:34
Новичок на форуме
Отправить личное сообщение для meam Посмотреть профиль Найти все сообщения от meam
 
Регистрация: 26.06.2013
Сообщений: 2

Сообщение от nerv_ Посмотреть сообщение
в одном месте так, в другом сяк
this.elem.on('submit', '.todo-form', $.proxy(this.onFormSubmit, this));
//...
this.list.on('click', '.todo-x', this.onXClick.bind(this));


говорит о незнании того, что ты делаешь
onFormSubmit: function(e) {
if(this.input.val().trim() === '') {
*!*
    return false;
*/!*
}
*!*
    e.preventDefault();
*/!*
}


оригинально
function TaskList(el) {
    var that = this;
    // ...
*!*
    this.list.on('click', '.todo-x', this.onXClick.bind(this));
    this.el.on('click', '.todo-remove', this.onRemoveClick.bind(that))
*/!*
}


и т.д.
исправил

Последний раз редактировалось meam, 21.08.2014 в 21:56.
Ответить с цитированием
  #4 (permalink)  
Старый 22.08.2014, 10:42
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Используешь метод trim стандарта ES5, но при этом используешь $.proxy...

Навешиваешь обработчик через addEventListener, но при этом используешь return false;

function TodoApp(opt) {
    // на один dom элемент навешиваешь события внутри TodoApp
    this.elem = opt.elem;
    this.taskList = new TaskList(this.elem);
    this.elem.on('submit', '.todo-form', $.proxy(this.onFormSubmit, this))
}

function TaskList(el) {
    var that = this;
    this.el = el;
    // и внутри TaskList
    this.el.on('click', '.todo-remove', $.proxy(this.onRemoveClick, this))
}

Беда.

Кто-то не знает, как передавать контекст в итерирующие методы...
var that = this;
        var oldTasks = that.tasks;
        that.tasks = [];
        oldTasks.forEach(function(e) {
            if(e.done) {
                $(e.li).remove();
            }else {
                that.tasks.push(e);
            }
        })


и т.д.
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #5 (permalink)  
Старый 22.08.2014, 11:16
Профессор
Отправить личное сообщение для WorM32 Посмотреть профиль Найти все сообщения от WorM32
 
Регистрация: 11.02.2014
Сообщений: 303

// jsDOC
function TodoApp(opt) {// лучше использовать полное options
    this.elem = opt.elem;
    this.taskList = new TaskList(this.elem);
    this.input = this.elem.find('.todo-name'); 
    this.elem.on('submit', '.todo-form', $.proxy(this.onFormSubmit, this)) //пропущена ;. Почему не просто this.onFormSubmit.bind(this)?

}
TodoApp.prototype = {
    constructor: TodoApp,
    onFormSubmit: function() { // параметр e
        if(this.input.val().trim() === '') { // this.input.val() в переменную, тк используется 2 раза.
            return false; // нет! только e.preventDefault. return false аналогично вызову e.preventDefault() и e.stopPropagation(), использовать stopPropagation плохой тон.
        }
        this.taskList.addTask(this.input.val());
        this.input.val('');
        return false;
    }
};
function TaskList(el) {
    var that = this;
    this.el = el; // el, elem - определись уже. к тому же el - это jQuery переменная, jQuery переменные лучше обозначать используя префикс $ (например, $el)
    this.list = el.find('.todo-list');
    this.tasks = [];
    this.list.on('dblclick', '.todo-task', function(e) { // неправильный подход. TaskList должен содержать коллекцию Task и оперерировать уже ими. Так что dbclick должен слушать и обарабывать Task.
        var task = $(e.currentTarget).data('task');
        var newName = prompt('', task.name);
        task.edit(newName);
    });
    this.list.on('change', '.todo-check', function(e) {
        var task = $(e.currentTarget).parent().data('task'); // parent() - зло
        task.onCheckChange();
    });
    this.list.on('click', '.todo-x', $.proxy(this.onXClick, this)); // это должно быть у Task во вьюхе
    this.el.on('click', '.todo-remove', $.proxy(this.onRemoveClick, this)) // ;

}
TaskList.prototype = {
    constructor: TaskList,
    addTask: function(name) {
        var li = $('<li/>').addClass('todo-task animated flash'); // неее. Должен быть TaskView, который будет этой хренью заниматься. А здесь должн создаваться модель Task и на основе модели TaskView
        this.list.append(li);
        var task = new Task(li, name);
        this.tasks.push(task);
        li.data('task', task); // не понятно, зачем засовывать в this.task и в data элемента. косяк
        console.log(this.tasks);
    },
    onXClick: function(e) {
        var task = $(e.currentTarget).parent('li').data('task');
        task.li.remove();
        this.tasks.forEach(function(e,i,a) {
            if(e === task) {
                a.splice(i,1)
            }
        })
    },
    onRemoveClick: function() {
        var that = this; // лишнее
        var oldTasks = that.tasks;
        that.tasks = [];
        oldTasks.forEach(function(e) { // можно использовать bind(this), либо передать конекст 3-им аргументом
            if(e.done) {
                $(e.li).remove(); // ну и опять же, здесь должно быть вызов модели Task
            }else {
                that.tasks.push(e);
            }
        })
    }
};
function Task(li ,name) {
    this.li = li;
    this.name = name;
    this.done = false;
    this.renderTask();
}
Task.prototype = {
    constructor: Task,
    renderTask: function() {
        this.li.html('<input type="checkbox" class="todo-check"> ' +this.name+ '<span class="todo-x"> X </span>');

    },
    edit: function(newName) {
        if(this.done) {
            this.done = false;
            this.li.removeClass('done') // ;
        }
        this.name = newName;
        this.renderTask();
    },
    onCheckChange: function() {
        this.li.toggleClass('done');
        this.done = !this.done;
    }

};
new TodoApp({
    elem: $('.todo') // ;
});


Вторую половину смотрел уже слабо, устал)

Последний раз редактировалось WorM32, 22.08.2014 в 11:23.
Ответить с цитированием
  #6 (permalink)  
Старый 22.08.2014, 11:22
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

new TodoApp({
    elem: $('.todo')
});

скрипт может быть вызван до загрузки дерева, а не после.

для того, чтобы уйти от этого, нужно вынести инициализацию в $(function () { /*КОД*/ });
и даже не в неё, а в :

jQuery(function ($) { /*КОД*/ });


потому что $ - это не всегда jQuery
Ответить с цитированием
  #7 (permalink)  
Старый 22.08.2014, 11:24
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

this.list.on('dblclick', '.todo-task', function(e) {
        var task = $(e.currentTarget).data('task');
        var newName = prompt('', task.name);
        task.edit(newName);
    });
    this.list.on('change', '.todo-check', function(e) {
        var task = $(e.currentTarget).parent().data('task');
        task.onCheckChange();
    });
    this.list.on('click', '.todo-x', $.proxy(this.onXClick, this));


обычно навешивание делается в один вызов. для этого передаётся карта имен событий к обработчикам. чё по чём - в документации показано.

... вообще, что делают обработчики событий в конструкторе? нужно вынести их в инициализацию, или что-то в этом роде (document.ready)
Ответить с цитированием
  #8 (permalink)  
Старый 22.08.2014, 11:25
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

function TaskList(el) {
    var that = this;
//...


так лучше не делать. конструктор легко может стать замыканием, а это очень плохо - при создании ~1000 объектов
Ответить с цитированием
  #9 (permalink)  
Старый 22.08.2014, 11:40
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Phil Karlton: «There are only two hard things in Computer Science: cache invalidation and naming things.»
(В программировании две беды: инвалидация кеша и именование переменных)

поговорим про вторую беду:

onXClick: function(e) {
        //..
    },
    onRemoveClick: function() {
        //..
    }


плохие имена для методов. в имени сущности (любой) должно быть показано, для чего она.

не глядя в код, сможешь рассказать, что внутри этих методов и зачем они? а для этих?
function SmileList () { }
SmileList.prototype = {
    // да, в классе 2 метода.
    // и если что-то сломается, то
    // для поиска бага в коде придется читать содержимое этих методов. 
    // и ЭТО НЕ ВЕСЕЛО, когда кода очень много.
    // и писал его не ты, а кто-то другой.
    click: function(e) {
        //..
    },
    mousedown: function() {
        //..
    }
};


для сравнения, это имя - получше, но тоже не то.
addTask: function(name) {
        //...
    },


ещё пример:

Task.prototype = {
    constructor: Task,
    renderTask: function() {
       /// ....
    },
    edit: function(newName) {
        //....
    },
    onCheckChange: function() {
        //...
    }

};


Task.renderTask - зачем постфикс (красный)?
Task.edit - неплохо

поподробнее про TaskList.addTask :

TaskList.addTask

какие сущности могут быть внутри TaskList ? ничего, кроме TASK. постфикс "Task" для addTask не нужен.

и, судя по названию класса, это упорядоченный список (List).

операция ДОБАВИТЬ (add) больше подходит для списков, где порядок не важен

пример такого списка - список классов HTML
var li = $('<li/>').*!*addClass*/!*('todo-task animated flash');


а там, где порядок важен, обычно именуют так:
this.list.*!*append*/!*(li);
this.tasks.*!*push*/!*(task)


append, push - отлично.


т.е. метод переименован из TaskList.addTask в TaskList.append.

вообще, имена для переменных - вопрос вкуса, конечно, но лучше именовать их так, чтобы было понятно о методе\переменной без залезания вовнутрь неё

Последний раз редактировалось melky, 22.08.2014 в 11:55.
Ответить с цитированием
  #10 (permalink)  
Старый 22.08.2014, 12:00
Профессор
Отправить личное сообщение для WorM32 Посмотреть профиль Найти все сообщения от WorM32
 
Регистрация: 11.02.2014
Сообщений: 303

melky,
ничего не вижу плохого в наименовании обработчиков событий
onXClick: function(e) {
        //..
    },
    onRemoveClick: function() {
        //..
    }
Сам использую такой же подход. Из названия сразу видно onЭлементClick, что это:
  • Обработчик события (префикс on). При беглом просмотре большого куска кода, сразу видно, какой метод связан с событиями, а какой нет.
  • Элемент взаимодействия (Элемент)
  • Название события (суффикс Click)
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как вызвать свою функцию из «чужого» кода в Java Script, не переписывая «чужой» код? korobochkin Библиотеки/Тулкиты/Фреймворки 2 19.07.2014 16:17
Как вы относитесь к наркоманам? Maxmaxmaximus7 Оффтопик 7 05.02.2014 13:29
Посоветуйте как улучшить код для работы с history api [ jquery + js + history api ] Geo Ваши сайты и скрипты 0 12.01.2014 00:41
Аккордеон меню, как доработать код. Gawk Общие вопросы Javascript 1 23.07.2012 13:01
Подскажите код как создать эффект... lopraeph Элементы интерфейса 1 09.06.2011 20:18